mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 11:16:57 +00:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
15ffab659c | |||
ca76a928c1 |
16
.github/dependabot.yml
vendored
16
.github/dependabot.yml
vendored
@ -6,19 +6,3 @@ updates:
|
||||
interval: daily
|
||||
time: "10:00"
|
||||
open-pull-requests-limit: 10
|
||||
ignore:
|
||||
#only allow patch updates for locale-data - this has to be updated manually due to codegen
|
||||
- dependency-name: pocketmine/locale-data
|
||||
update-types:
|
||||
- "version-update:semver-major"
|
||||
- "version-update:semver-minor"
|
||||
|
||||
- package-ecosystem: gitsubmodule
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
|
BIN
.github/readme/pocketmine-dark.png
vendored
BIN
.github/readme/pocketmine-dark.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
BIN
.github/readme/pocketmine.png
vendored
BIN
.github/readme/pocketmine.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
104
.github/workflows/build-docker-image.yml
vendored
104
.github/workflows/build-docker-image.yml
vendored
@ -1,104 +0,0 @@
|
||||
name: Update Docker Hub images
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Update Docker Hub images
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Clone pmmp/PocketMine-Docker repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: pmmp/PocketMine-Docker
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Get tag names
|
||||
id: tag-name
|
||||
run: |
|
||||
VERSION=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{')
|
||||
echo TAG_NAME=$VERSION >> $GITHUB_OUTPUT
|
||||
echo MAJOR=$(echo $VERSION | cut -d. -f1) >> $GITHUB_OUTPUT
|
||||
echo MINOR=$(echo $VERSION | cut -d. -f1-2) >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Download new release information
|
||||
run: curl -f -L ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.tag-name.outputs.TAG_NAME }}/build_info.json -o new_build_info.json
|
||||
|
||||
- name: Detect channel
|
||||
id: channel
|
||||
run: echo CHANNEL=$(jq -r '.channel' new_build_info.json) >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get name of Docker repository name
|
||||
id: docker-repo-name
|
||||
run: echo NAME=$(echo "${GITHUB_REPOSITORY,,}") >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build image for tag
|
||||
uses: docker/build-push-action@v4.0.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
tags: |
|
||||
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
build-args: |
|
||||
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
PMMP_REPO=${{ github.repository }}
|
||||
|
||||
- name: Build image for major tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v4.0.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
tags: |
|
||||
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MAJOR }}
|
||||
ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MAJOR }}
|
||||
build-args: |
|
||||
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
PMMP_REPO=${{ github.repository }}
|
||||
|
||||
- name: Build image for minor tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v4.0.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
tags: |
|
||||
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MINOR }}
|
||||
ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MINOR }}
|
||||
build-args: |
|
||||
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
PMMP_REPO=${{ github.repository }}
|
||||
|
||||
- name: Build image for latest tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v4.0.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
tags: |
|
||||
${{ steps.docker-repo-name.outputs.NAME }}:latest
|
||||
ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:latest
|
||||
build-args: |
|
||||
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
PMMP_REPO=${{ github.repository }}
|
101
.github/workflows/discord-release-embed.php
vendored
101
.github/workflows/discord-release-embed.php
vendored
@ -1,101 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\utils\Internet;
|
||||
use function dirname;
|
||||
use function fwrite;
|
||||
use function is_array;
|
||||
use function json_decode;
|
||||
use function json_encode;
|
||||
use const JSON_THROW_ON_ERROR;
|
||||
use const STDERR;
|
||||
|
||||
require dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* @phpstan-return array<string, mixed>
|
||||
*/
|
||||
function generateDiscordEmbed(string $version, string $channel, string $description, string $detailsUrl, string $sourceUrl, string $pharDownloadUrl, string $buildLogUrl, int $newsPingRoleId) : array{
|
||||
return [
|
||||
"content" => "<@&$newsPingRoleId> New PocketMine-MP release: $version ($channel)",
|
||||
"embeds" => [
|
||||
[
|
||||
"title" => "New PocketMine-MP release: $version ($channel)",
|
||||
"description" => <<<DESCRIPTION
|
||||
$description
|
||||
|
||||
[Details]($detailsUrl) | [Source Code]($sourceUrl) | [Build Log]($buildLogUrl) | [Download]($pharDownloadUrl)
|
||||
DESCRIPTION,
|
||||
"url" => $detailsUrl,
|
||||
"color" => $channel === "stable" ? 0x57ab5a : 0xc69026
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
if(count($argv) !== 6){
|
||||
fwrite(STDERR, "Required arguments: github repo, version, API token, webhook URL, ping role ID\n");
|
||||
exit(1);
|
||||
}
|
||||
[, $repo, $tagName, $token, $hookURL, $newsPingRoleId] = $argv;
|
||||
|
||||
$result = Internet::getURL('https://api.github.com/repos/' . $repo . '/releases/tags/' . $tagName, extraHeaders: [
|
||||
'Authorization: token ' . $token
|
||||
]);
|
||||
if($result === null){
|
||||
fwrite(STDERR, "failed to access GitHub API\n");
|
||||
return;
|
||||
}
|
||||
if($result->getCode() !== 200){
|
||||
fwrite(STDERR, "Error accessing GitHub API: " . $result->getCode() . "\n");
|
||||
fwrite(STDERR, $result->getBody() . "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$releaseInfoJson = json_decode($result->getBody(), true, JSON_THROW_ON_ERROR);
|
||||
if(!is_array($releaseInfoJson)){
|
||||
fwrite(STDERR, "Invalid release JSON returned from GitHub API\n");
|
||||
exit(1);
|
||||
}
|
||||
$buildInfoPath = 'https://github.com/' . $repo . '/releases/download/' . $tagName . '/build_info.json';
|
||||
|
||||
$buildInfoResult = Internet::getURL($buildInfoPath, extraHeaders: [
|
||||
'Authorization: token ' . $token
|
||||
]);
|
||||
if($buildInfoResult === null){
|
||||
fwrite(STDERR, "missing build_info.json\n");
|
||||
exit(1);
|
||||
}
|
||||
if($buildInfoResult->getCode() !== 200){
|
||||
fwrite(STDERR, "error accessing build_info.json: " . $buildInfoResult->getCode() . "\n");
|
||||
fwrite(STDERR, $buildInfoResult->getBody() . "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$buildInfoJson = json_decode($buildInfoResult->getBody(), true, JSON_THROW_ON_ERROR);
|
||||
if(!is_array($buildInfoJson)){
|
||||
fwrite(STDERR, "invalid build_info.json\n");
|
||||
exit(1);
|
||||
}
|
||||
$detailsUrl = $buildInfoJson["details_url"];
|
||||
$sourceUrl = $buildInfoJson["source_url"];
|
||||
$pharDownloadUrl = $buildInfoJson["download_url"];
|
||||
$buildLogUrl = $buildInfoJson["build_log_url"];
|
||||
|
||||
$description = $releaseInfoJson["body"];
|
||||
|
||||
$discordPayload = generateDiscordEmbed($buildInfoJson["base_version"], $buildInfoJson["channel"], $description, $detailsUrl, $sourceUrl, $pharDownloadUrl, $buildLogUrl, (int) $newsPingRoleId);
|
||||
|
||||
$response = Internet::postURL(
|
||||
$hookURL,
|
||||
json_encode($discordPayload, JSON_THROW_ON_ERROR),
|
||||
extraHeaders: ['Content-Type: application/json']
|
||||
);
|
||||
if($response?->getCode() !== 204){
|
||||
fwrite(STDERR, "failed to send Discord webhook\n");
|
||||
fwrite(STDERR, $response?->getBody() ?? "no response body\n");
|
||||
exit(1);
|
||||
}
|
38
.github/workflows/discord-release-notify.yml
vendored
38
.github/workflows/discord-release-notify.yml
vendored
@ -1,38 +0,0 @@
|
||||
name: Notify Discord webhook of release
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.25.2
|
||||
with:
|
||||
php-version: 8.1
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-dev --prefer-dist --no-interaction --ignore-platform-reqs
|
||||
|
||||
- name: Get actual tag name
|
||||
id: tag-name
|
||||
run: echo TAG_NAME=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{') >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Run webhook post script
|
||||
run: php .github/workflows/discord-release-embed.php ${{ github.repository }} ${{ steps.tag-name.outputs.TAG_NAME }} ${{ github.token }} ${{ secrets.DISCORD_RELEASE_WEBHOOK }} ${{ secrets.DISCORD_NEWS_PING_ROLE_ID }}
|
67
.github/workflows/draft-release.yml
vendored
67
.github/workflows/draft-release.yml
vendored
@ -13,17 +13,17 @@ jobs:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@2.25.2
|
||||
uses: shivammathur/setup-php@2.12.0
|
||||
with:
|
||||
php-version: 8.1
|
||||
php-version: 8.0
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
@ -40,10 +40,33 @@ jobs:
|
||||
run: |
|
||||
BUILD_NUMBER=$((2000+$GITHUB_RUN_NUMBER)) #to stay above jenkins
|
||||
echo "Build number: $BUILD_NUMBER"
|
||||
echo BUILD_NUMBER=$BUILD_NUMBER >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=BUILD_NUMBER::$BUILD_NUMBER
|
||||
|
||||
- name: Minify BedrockData JSON files
|
||||
run: php vendor/pocketmine/bedrock-data/.minify_json.php
|
||||
run: php src/pocketmine/resources/vanilla/.minify_json.php
|
||||
|
||||
- name: Run preprocessor
|
||||
run: |
|
||||
PM_PREPROCESSOR_PATH="$GITHUB_WORKSPACE/build/preprocessor"
|
||||
php "$PM_PREPROCESSOR_PATH/PreProcessor.php" --path=src --multisize || (echo "Preprocessor exited with code $?" && exit 1)
|
||||
#dump the diff of preprocessor replacements to a patch in case it has bugs
|
||||
git diff > preprocessor_diff.patch
|
||||
VENDOR_PM="$GITHUB_WORKSPACE/vendor"
|
||||
VENDOR_PM_BACKUP="$GITHUB_WORKSPACE/vendor-before-preprocess"
|
||||
cp -r "$VENDOR_PM" "$VENDOR_PM_BACKUP"
|
||||
for f in $(ls $VENDOR_PM/pocketmine); do
|
||||
echo "Processing directory \"$f\"..."
|
||||
php "$PM_PREPROCESSOR_PATH/PreProcessor.php" --path="$VENDOR_PM/pocketmine/$f/src" --multisize || (echo "Preprocessor exited with code $?" && exit 1)
|
||||
echo "Checking for changes in \"$f\"..."
|
||||
DIFF=$(git diff --no-index "$VENDOR_PM_BACKUP/pocketmine/$f" "$VENDOR_PM/pocketmine/$f" || true)
|
||||
if [ "$DIFF" != "" ]; then
|
||||
PATCH="$GITHUB_WORKSPACE/preprocessor_diff_$f.patch"
|
||||
echo "$DIFF" > "$PATCH"
|
||||
echo "Generated patch file \"$PATCH\""
|
||||
else
|
||||
echo "No diff generated for \"$f\" (preprocessor made no changes)"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Build PocketMine-MP.phar
|
||||
run: php -dphar.readonly=0 build/server-phar.php --git ${{ github.sha }} --build ${{ steps.build-number.outputs.BUILD_NUMBER }}
|
||||
@ -51,18 +74,16 @@ jobs:
|
||||
- name: Get PocketMine-MP release version
|
||||
id: get-pm-version
|
||||
run: |
|
||||
echo PM_VERSION=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BASE_VERSION;') >> $GITHUB_OUTPUT
|
||||
echo MCPE_VERSION=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK;') >> $GITHUB_OUTPUT
|
||||
echo PM_VERSION_SHORT=$(php -r 'require "vendor/autoload.php"; $v = explode(".", \pocketmine\VersionInfo::BASE_VERSION); array_pop($v); echo implode(".", $v);') >> $GITHUB_OUTPUT
|
||||
echo PM_VERSION_MD=$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);') >> $GITHUB_OUTPUT
|
||||
echo CHANGELOG_SUFFIX=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "" : "-" . \pocketmine\VersionInfo::BUILD_CHANNEL;') >> $GITHUB_OUTPUT
|
||||
echo PRERELEASE=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "false" : "true";') >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=PM_VERSION::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\BASE_VERSION;')
|
||||
echo ::set-output name=MCPE_VERSION::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK;')
|
||||
echo ::set-output name=PM_VERSION_SHORT::$(php -r 'require "vendor/autoload.php"; $v = explode(".", \pocketmine\BASE_VERSION); array_pop($v); echo implode(".", $v);')
|
||||
echo ::set-output name=PM_VERSION_MD::$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\BASE_VERSION);')
|
||||
|
||||
- name: Generate build info
|
||||
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} ${{ github.run_id }} > build_info.json
|
||||
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} > build_info.json
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: release_artifacts
|
||||
path: |
|
||||
@ -71,16 +92,28 @@ jobs:
|
||||
${{ github.workspace }}/build_info.json
|
||||
|
||||
- name: Create draft release
|
||||
uses: ncipollo/release-action@v1.12.0
|
||||
uses: ncipollo/release-action@v1.8.6
|
||||
with:
|
||||
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
|
||||
commit: ${{ github.sha }}
|
||||
draft: true
|
||||
prerelease: ${{ steps.get-pm-version.outputs.PRERELEASE }}
|
||||
name: PocketMine-MP ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
||||
tag: ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body: |
|
||||
**For Minecraft: Bedrock Edition ${{ steps.get-pm-version.outputs.MCPE_VERSION }}**
|
||||
|
||||
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}${{ steps.get-pm-version.outputs.CHANGELOG_SUFFIX }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
|
||||
Please see the [changelogs](/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
|
||||
|
||||
## WARNING
|
||||
|
||||
The 3.x line of releases is now OBSOLETE. It will be discontinued after **March 1st, 2022**.
|
||||
Please prepare to upgrade to 4.0 or newer before that date.
|
||||
|
||||
- name: Upload preprocessor diffs
|
||||
uses: actions/upload-artifact@v2
|
||||
if: always()
|
||||
with:
|
||||
name: preprocessor_diffs
|
||||
path: ${{ github.workspace }}/preprocessor_diff*.patch
|
||||
|
||||
|
139
.github/workflows/main.yml
vendored
139
.github/workflows/main.yml
vendored
@ -6,28 +6,47 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-php:
|
||||
name: Prepare PHP
|
||||
runs-on: ${{ matrix.image }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.11]
|
||||
|
||||
steps:
|
||||
- name: Build and prepare PHP cache
|
||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
|
||||
phpstan:
|
||||
name: PHPStan analysis
|
||||
needs: build-php
|
||||
runs-on: ${{ matrix.image }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: ["8.1", "8.2"]
|
||||
php: [8.0.11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "5"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
@ -37,32 +56,35 @@ jobs:
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --prefer-dist --no-interaction
|
||||
run: php composer.phar install --prefer-dist --no-interaction
|
||||
|
||||
- name: Run PHPStan
|
||||
run: ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
|
||||
|
||||
phpunit:
|
||||
name: PHPUnit tests
|
||||
needs: build-php
|
||||
runs-on: ${{ matrix.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: ["8.1", "8.2"]
|
||||
php: [8.0.11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "5"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
@ -72,34 +94,37 @@ jobs:
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --prefer-dist --no-interaction
|
||||
run: php composer.phar install --prefer-dist --no-interaction
|
||||
|
||||
- name: Run PHPUnit tests
|
||||
run: ./vendor/bin/phpunit --bootstrap vendor/autoload.php --fail-on-warning tests/phpunit
|
||||
|
||||
integration:
|
||||
name: Integration tests
|
||||
needs: build-php
|
||||
runs-on: ${{ matrix.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: ["8.1", "8.2"]
|
||||
php: [8.0.11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "5"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
@ -109,32 +134,37 @@ jobs:
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-dev --prefer-dist --no-interaction
|
||||
run: php composer.phar install --no-dev --prefer-dist --no-interaction
|
||||
|
||||
- name: Run integration tests
|
||||
run: ./tests/travis.sh -t4
|
||||
|
||||
codegen:
|
||||
name: Generated Code consistency checks
|
||||
preprocessor:
|
||||
name: Preprocessor tests
|
||||
needs: build-php
|
||||
runs-on: ${{ matrix.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: ["8.1", "8.2"]
|
||||
php: [8.0.11]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
uses: pmmp/setup-php-action@e232f72a4330a07aae8418e8aa56b64efcdda636
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "5"
|
||||
|
||||
- name: Install Composer
|
||||
run: curl -sS https://getcomposer.org/installer | php
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
@ -144,24 +174,39 @@ jobs:
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-dev --prefer-dist --no-interaction
|
||||
run: php composer.phar install --no-dev --prefer-dist --no-interaction
|
||||
|
||||
- name: Regenerate registry annotations
|
||||
run: php build/generate-registry-annotations.php src
|
||||
|
||||
- name: Regenerate KnownTranslation APIs
|
||||
run: php build/generate-known-translation-apis.php
|
||||
|
||||
- name: Regenerate RuntimeEnum(De)serializer
|
||||
run: php build/generate-runtime-enum-serializers.php
|
||||
|
||||
- name: Regenerate BedrockData available files constants
|
||||
run: php build/generate-bedrockdata-path-consts.php
|
||||
|
||||
- name: Verify code is unchanged
|
||||
- name: Run preprocessor
|
||||
run: |
|
||||
git diff
|
||||
git diff --quiet
|
||||
PM_PREPROCESSOR_PATH="$GITHUB_WORKSPACE/build/preprocessor"
|
||||
php "$PM_PREPROCESSOR_PATH/PreProcessor.php" --path=src --multisize || (echo "Preprocessor exited with code $?" && exit 1)
|
||||
|
||||
#dump the diff of preprocessor replacements to a patch in case it has bugs
|
||||
git diff > preprocessor_diff.patch
|
||||
|
||||
VENDOR_PM="$GITHUB_WORKSPACE/vendor"
|
||||
VENDOR_PM_BACKUP="$GITHUB_WORKSPACE/vendor-before-preprocess"
|
||||
cp -r "$VENDOR_PM" "$VENDOR_PM_BACKUP"
|
||||
for f in $(ls $VENDOR_PM/pocketmine); do
|
||||
echo "Processing directory \"$f\"..."
|
||||
php "$PM_PREPROCESSOR_PATH/PreProcessor.php" --path="$VENDOR_PM/pocketmine/$f/src" --multisize || (echo "Preprocessor exited with code $?" && exit 1)
|
||||
echo "Checking for changes in \"$f\"..."
|
||||
DIFF=$(git diff --no-index "$VENDOR_PM_BACKUP/pocketmine/$f" "$VENDOR_PM/pocketmine/$f" || true)
|
||||
if [ "$DIFF" != "" ]; then
|
||||
PATCH="$GITHUB_WORKSPACE/preprocessor_diff_$f.patch"
|
||||
echo "$DIFF" > "$PATCH"
|
||||
echo "Generated patch file \"$PATCH\""
|
||||
else
|
||||
echo "No diff generated for \"$f\" (preprocessor made no changes)"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Upload preprocessor diffs
|
||||
uses: actions/upload-artifact@v2
|
||||
if: always()
|
||||
with:
|
||||
name: preprocessor_diffs_${{ matrix.php }}_${{ matrix.image }}
|
||||
path: ${{ github.workspace }}/preprocessor_diff*.patch
|
||||
|
||||
codestyle:
|
||||
name: Code Style checks
|
||||
@ -170,15 +215,13 @@ jobs:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.25.2
|
||||
uses: shivammathur/setup-php@2.15.0
|
||||
with:
|
||||
php-version: 8.1
|
||||
tools: php-cs-fixer:3.16
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
php-version: 8.0
|
||||
tools: php-cs-fixer:3.2
|
||||
|
||||
- name: Run PHP-CS-Fixer
|
||||
run: php-cs-fixer fix --dry-run --diff --ansi
|
||||
run: php-cs-fixer fix --dry-run --diff
|
||||
|
11
.github/workflows/support.yml
vendored
11
.github/workflows/support.yml
vendored
@ -8,19 +8,12 @@ jobs:
|
||||
support:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/support-requests@v3
|
||||
- uses: dessant/support-requests@v2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
support-label: "Support request"
|
||||
issue-comment: >
|
||||
Hi, we only accept **bug reports** on this issue tracker, but this issue looks like a support request.
|
||||
|
||||
|
||||
Instead of creating an issue, try the following:
|
||||
|
||||
- Check our [Documentation](https://doc.pmmp.io) to see if you can find answers there
|
||||
|
||||
- Ask the community on our [Discord server](https://discord.gg/bmSAZBG) or our [Forums](https://forums.pmmp.io)
|
||||
Thanks, but this issue tracker is not intended for support requests. Please read the guidelines on [submitting an issue](https://github.com/pmmp/PocketMine-MP/blob/master/CONTRIBUTING.md#creating-an-issue).
|
||||
|
||||
|
||||
[Docs](https://pmmp.rtfd.io) | [Discord](https://discord.gg/bmSAZBG) | [Forums](https://forums.pmmp.io)
|
||||
|
49
.github/workflows/update-php-versions.php
vendored
Normal file
49
.github/workflows/update-php-versions.php
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const VERSIONS = [
|
||||
"8.0"
|
||||
];
|
||||
|
||||
$workflowFile = file_get_contents(__DIR__ . '/main.yml');
|
||||
$newWorkflowFile = $workflowFile;
|
||||
foreach(VERSIONS as $v){
|
||||
$releaseInfo = file_get_contents("https://secure.php.net/releases?json&version=$v");
|
||||
if($releaseInfo === false){
|
||||
throw new \RuntimeException("Failed to contact php.net API");
|
||||
}
|
||||
$data = json_decode($releaseInfo, true);
|
||||
if(!is_array($data) || !isset($data["version"]) || !is_string($data["version"]) || preg_match('/^\d+\.\d+\.\d+(-[A-Za-z\d]+)?$/', $data["version"]) === 0){
|
||||
throw new \RuntimeException("Invalid data returned by API");
|
||||
}
|
||||
$updated = preg_replace("/$v\.\d+/", $data["version"], $newWorkflowFile);
|
||||
if($updated !== $newWorkflowFile){
|
||||
echo "Updated $v revision to " . $data["version"] . "\n";
|
||||
}
|
||||
$newWorkflowFile = $updated;
|
||||
}
|
||||
|
||||
if($workflowFile !== $newWorkflowFile){
|
||||
echo "Writing modified workflow file\n";
|
||||
file_put_contents(__DIR__ . '/main.yml', $newWorkflowFile);
|
||||
}
|
61
.github/workflows/update-updater-api.yml
vendored
61
.github/workflows/update-updater-api.yml
vendored
@ -13,70 +13,25 @@ jobs:
|
||||
- name: Install jq
|
||||
run: sudo apt update && sudo apt install jq -y
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/update.pmmp.io
|
||||
repository: pmmp/update.pmmp.io
|
||||
ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }}
|
||||
|
||||
- name: Get actual tag name
|
||||
id: tag-name
|
||||
run: echo TAG_NAME=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{') >> $GITHUB_OUTPUT
|
||||
run: echo ::set-output name=TAG_NAME::$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{')
|
||||
|
||||
- name: Download new release information
|
||||
run: curl -f -L ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.tag-name.outputs.TAG_NAME }}/build_info.json -o new_build_info.json
|
||||
|
||||
- name: Detect channels
|
||||
- name: Detect channel
|
||||
id: channel
|
||||
run: echo ::set-output name=CHANNEL::$(jq -r '.channel' new_build_info.json)
|
||||
|
||||
- name: Copy release information
|
||||
run: |
|
||||
CHANNEL=$(jq -r '.channel' new_build_info.json)
|
||||
VERSION=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
echo CHANNEL=$CHANNEL >> $GITHUB_OUTPUT
|
||||
if [ "$CHANNEL" == "stable" ]; then
|
||||
echo MAJOR=$(echo $VERSION | cut -d. -f1) >> $GITHUB_OUTPUT
|
||||
echo MINOR=$(echo $VERSION | cut -d. -f1-2) >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo MAJOR=$(echo $VERSION | cut -d. -f1)-$CHANNEL >> $GITHUB_OUTPUT
|
||||
echo MINOR=$(echo $VERSION | cut -d. -f1-2)-$CHANNEL >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Update channel info
|
||||
run: |
|
||||
function version_id() {
|
||||
major=$(echo $1 | cut -d. -f1)
|
||||
minor=$(echo $1 | cut -d. -f2)
|
||||
patch=$(echo $1 | cut -d. -f3)
|
||||
echo $(((major * 1000000) + (minor * 1000) + patch))
|
||||
}
|
||||
|
||||
function update_channel() {
|
||||
local target_file_name="$1"
|
||||
local new_file_name="$2"
|
||||
|
||||
local old_version_id
|
||||
local new_version_id
|
||||
|
||||
if [ ! -f "$target_file_name" ]; then
|
||||
echo "Creating channel file: $target_file_name"
|
||||
cp "$new_file_name" "$target_file_name"
|
||||
else
|
||||
old_version_id=$(version_id "$(jq -r '.base_version' "$target_file_name")")
|
||||
new_version_id=$(version_id "$(jq -r '.base_version' "$new_file_name")")
|
||||
|
||||
echo "Old version ID: $old_version_id"
|
||||
echo "New version ID: $new_version_id"
|
||||
|
||||
if [ $new_version_id -ge $old_version_id ]; then #suffixed versions will have the same version ID - assume they'll always be newer
|
||||
echo "Updating channel file: $target_file_name ($old_version_id -> $new_version_id)"
|
||||
cp "$new_file_name" "$target_file_name"
|
||||
else
|
||||
echo "Version $new_version_id is less than $old_version_id, not updating channel file: $target_file_name"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
update_channel "channels/${{ steps.channel.outputs.CHANNEL }}.json" "new_build_info.json"
|
||||
update_channel "channels/${{ steps.channel.outputs.MAJOR }}.json" "new_build_info.json"
|
||||
update_channel "channels/${{ steps.channel.outputs.MINOR }}.json" "new_build_info.json"
|
||||
cp new_build_info.json channels/${{ steps.channel.outputs.CHANNEL }}.json
|
||||
rm new_build_info.json
|
||||
|
||||
- name: Commit changes
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,7 +1,5 @@
|
||||
players/*
|
||||
worlds/*
|
||||
world_conversion_backups/*
|
||||
backups/*
|
||||
plugin_data/*
|
||||
plugins/*
|
||||
bin*/*
|
||||
@ -12,7 +10,6 @@ crashdumps/*
|
||||
*.phar
|
||||
server.properties
|
||||
/pocketmine.yml
|
||||
/plugin_list.yml
|
||||
memory_dumps/*
|
||||
resource_packs/
|
||||
server.lock
|
||||
|
9
.gitmodules
vendored
9
.gitmodules
vendored
@ -1,6 +1,15 @@
|
||||
[submodule "src/pocketmine/lang/locale"]
|
||||
path = src/pocketmine/lang/locale
|
||||
url = https://github.com/pmmp/Language.git
|
||||
[submodule "tests/preprocessor"]
|
||||
path = build/preprocessor
|
||||
url = https://github.com/pmmp/preprocessor.git
|
||||
[submodule "tests/plugins/DevTools"]
|
||||
path = tests/plugins/DevTools
|
||||
url = https://github.com/pmmp/DevTools.git
|
||||
[submodule "build/php"]
|
||||
path = build/php
|
||||
url = https://github.com/pmmp/php-build-scripts.git
|
||||
[submodule "src/pocketmine/resources/vanilla"]
|
||||
path = src/pocketmine/resources/vanilla
|
||||
url = https://github.com/pmmp/BedrockData.git
|
||||
|
12
.idea/codeStyles/Project.xml
generated
12
.idea/codeStyles/Project.xml
generated
@ -30,13 +30,6 @@
|
||||
<option name="USE_TAB_CHARACTER" value="true" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="Markdown">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="PHP">
|
||||
<option name="CLASS_BRACE_STYLE" value="1" />
|
||||
<option name="METHOD_BRACE_STYLE" value="1" />
|
||||
@ -69,11 +62,6 @@
|
||||
<option name="USE_TAB_CHARACTER" value="true" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="Shell Script">
|
||||
<indentOptions>
|
||||
<option name="USE_TAB_CHARACTER" value="true" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="neon">
|
||||
<indentOptions>
|
||||
<option name="USE_TAB_CHARACTER" value="true" />
|
||||
|
2
.idea/fileTemplates/includes/PHP File Header.php
generated
2
.idea/fileTemplates/includes/PHP File Header.php
generated
@ -16,6 +16,6 @@
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
@ -4,8 +4,9 @@ $finder = PhpCsFixer\Finder::create()
|
||||
->in(__DIR__ . '/src')
|
||||
->in(__DIR__ . '/build')
|
||||
->in(__DIR__ . '/tests')
|
||||
->in(__DIR__ . '/tools')
|
||||
->notPath('plugins/DevTools')
|
||||
->notPath('preprocessor')
|
||||
->notContains('#ifndef COMPILE') //preprocessor will break if these are changed
|
||||
->notName('PocketMine.php');
|
||||
|
||||
return (new PhpCsFixer\Config)
|
||||
@ -42,41 +43,11 @@ return (new PhpCsFixer\Config)
|
||||
'import_functions' => true,
|
||||
'import_classes' => null,
|
||||
],
|
||||
'header_comment' => [
|
||||
'comment_type' => 'comment',
|
||||
'header' => <<<BODY
|
||||
|
||||
____ _ _ __ __ _ __ __ ____
|
||||
| _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
| |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
| __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
|_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
@author PocketMine Team
|
||||
@link http://www.pocketmine.net/
|
||||
|
||||
|
||||
BODY,
|
||||
'location' => 'after_open'
|
||||
],
|
||||
'indentation_type' => true,
|
||||
'logical_operators' => true,
|
||||
'native_constant_invocation' => [
|
||||
'scope' => 'namespaced'
|
||||
],
|
||||
'native_function_invocation' => [
|
||||
'scope' => 'namespaced',
|
||||
'include' => ['@all'],
|
||||
],
|
||||
'new_with_braces' => [
|
||||
'named_class' => true,
|
||||
'anonymous_class' => false,
|
||||
],
|
||||
'no_closing_tag' => true,
|
||||
'no_empty_phpdoc' => true,
|
||||
'no_extra_blank_lines' => true,
|
||||
@ -95,12 +66,6 @@ BODY,
|
||||
],
|
||||
'sort_algorithm' => 'alpha'
|
||||
],
|
||||
'phpdoc_align' => [
|
||||
'align' => 'vertical',
|
||||
'tags' => [
|
||||
'param',
|
||||
]
|
||||
],
|
||||
'phpdoc_line_span' => [
|
||||
'property' => 'single',
|
||||
'method' => null,
|
||||
|
21
BUILDING.md
21
BUILDING.md
@ -2,32 +2,43 @@
|
||||
## Pre-requisites
|
||||
- A bash shell (git bash is sufficient for Windows)
|
||||
- [`git`](https://git-scm.com) available in your shell
|
||||
- PHP 8.1 or newer available in your shell
|
||||
- PHP 8.0 or newer available in your shell
|
||||
- [`composer`](https://getcomposer.org) available in your shell
|
||||
|
||||
## Custom PHP binaries
|
||||
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
|
||||
|
||||
- [Prebuilt binaries](https://github.com/pmmp/PHP-Binaries/releases)
|
||||
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-8.0-Aggregate)
|
||||
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
|
||||
|
||||
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
|
||||
|
||||
## Setting up environment
|
||||
1. `git clone https://github.com/pmmp/PocketMine-MP.git`
|
||||
1. `git clone --recursive https://github.com/pmmp/PocketMine-MP.git`
|
||||
2. `composer install`
|
||||
|
||||
## Checking out a different branch to build
|
||||
1. `git checkout <branch to checkout>`
|
||||
2. Re-run `composer install` to synchronize dependencies.
|
||||
2. `git submodule update --init`
|
||||
3. Re-run `composer install` to synchronize dependencies.
|
||||
|
||||
## Optimizing for release builds
|
||||
1. Add the flags `--no-dev --classmap-authoritative` to your `composer install` command. This will reduce build size and improve autoloading speed.
|
||||
2. Preprocess the source code by running `build/preprocessor/PreProcessor.php`. Usage instructions are provided in `build/preprocessor/README.md`.
|
||||
|
||||
### Note
|
||||
Preprocessor requires that the `cpp` (c preprocessor) is available in your PATH.
|
||||
|
||||
## Building `PocketMine-MP.phar`
|
||||
Run `composer make-server` using your preferred PHP binary. It'll drop a `PocketMine-MP.phar` into the current working directory.
|
||||
|
||||
You can also use the `--out` option to change the output filename.
|
||||
|
||||
There is a bug in PHP that might cause an error which looks like this:
|
||||
```
|
||||
Fatal error: Uncaught BadMethodCallException: unable to create temporary file in PocketMine-MP/build/server-phar.php:119
|
||||
```
|
||||
You can work around it by setting `ulimit -n` to some bigger number, e.g. `8192`, or by updating your PHP version to at least 8.0.3.
|
||||
|
||||
## Running PocketMine-MP from source code
|
||||
Run `src/PocketMine.php` using your preferred PHP binary.
|
||||
Run `src/pocketmine/PocketMine.php` using your preferred PHP binary.
|
||||
|
@ -18,59 +18,6 @@ Larger contributions like feature additions should be preceded by a [Change Prop
|
||||
## Other things you'll need
|
||||
- [git](https://git-scm.com/)
|
||||
|
||||
## List of `pocketmine` namespaces which are in other repos
|
||||
PocketMine-MP has several dependencies which are independent from the main server code. Most of them use the `pocketmine` namespace.
|
||||
Some of these add extra classes to packages which already exist in PocketMine-MP.
|
||||
|
||||
Take a look at the table below if you can't find the class or function you're looking for.
|
||||
|
||||
| Source URL | Namespace, class or function |
|
||||
|:----------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [pmmp/BedrockProtocol](https://github.com/pmmp/BedrockProtocol) | `pocketmine\network\mcpe\protocol` |
|
||||
| [pmmp/BinaryUtils](https://github.com/pmmp/BinaryUtils) | `pocketmine\utils\BinaryDataException`</br>`pocketmine\utils\BinaryStream`</br>`pocketmine\utils\Binary` |
|
||||
| [pmmp/Color](https://github.com/pmmp/Color) | `pocketmine\color` |
|
||||
| [pmmp/ErrorHandler](https://github.com/pmmp/ErrorHandler) | `pocketmine\errorhandler` |
|
||||
| [pmmp/Log](https://github.com/pmmp/Log) | `AttachableLogger`</br>`BufferedLogger`</br>`GlobalLogger`</br>`LogLevel`</br>`Logger`</br>`PrefixedLogger`</br>`SimpleLogger` |
|
||||
| [pmmp/Math](https://github.com/pmmp/Math) | `pocketmine\math` |
|
||||
| [pmmp/NBT](https://github.com/pmmp/NBT) | `pocketmine\nbt` |
|
||||
| [pmmp/RakLibIpc](https://github.com/pmmp/RakLibIpc) | `raklib\server\ipc` |
|
||||
| [pmmp/RakLib](https://github.com/pmmp/RakLib) | `raklib` |
|
||||
| [pmmp/Snooze](https://github.com/pmmp/Snooze) | `pocketmine\snooze` |
|
||||
| [pmmp/ext-chunkutils2](https://github.com/pmmp/ext-chunkutils2) | `pocketmine\world\format\LightArray`</br>`pocketmine\world\format\PalettedBlockArray`</br>`pocketmine\world\format\io\SubChunkConverter` |
|
||||
| [pmmp/ext-morton](https://github.com/pmmp/ext-morton) | `morton2d_decode`</br>`morton2d_encode`</br>`morton3d_decode`</br>`morton3d_encode` |
|
||||
| [pmmp/ext-libdeflate](https://github.com/pmmp/ext-libdeflate) | `libdeflate_deflate_compress`</br>`libdeflate_gzip_compress`</br>`libdeflate_zlib_compress` |
|
||||
|
||||
## Choosing a target branch
|
||||
PocketMine-MP has three primary branches of development.
|
||||
|
||||
| Type of change | `stable` | `minor-next` | `major-next` |
|
||||
|:--------------------------------------------------------------------------------------------|:--------:|:-------------------------------:|:------------:|
|
||||
| Bug fixes | ✔️ | ✔️ | ✔️ |
|
||||
| Improvements to API docs | ✔️ | ✔️ | ✔️ |
|
||||
| Cleaning up code | ❌ | ✔️ | ✔️ |
|
||||
| Changing code formatting or style | ❌ | ✔️ | ✔️ |
|
||||
| Addition of new core features | ❌ | 🟡 Only if non-disruptive | ✔️ |
|
||||
| Changing core behaviour (e.g. making something use threads) | ❌ | ✔️ | ✔️ |
|
||||
| Addition of new configuration options | ❌ | 🟡 Only if optional | ✔️ |
|
||||
| Addition of new API classes, methods or constants | ❌ | ✔️ | ✔️ |
|
||||
| Deprecating API classes, methods or constants | ❌ | ✔️ | ✔️ |
|
||||
| Adding optional parameters to an API method | ❌ | ✔️ | ✔️ |
|
||||
| Changing API behaviour | ❌ | 🟡 Only if backwards-compatible | ✔️ |
|
||||
| Removal of API | ❌ | ❌ | ✔️ |
|
||||
| Backwards-incompatible API change (e.g. renaming a method) | ❌ | ❌ | ✔️ |
|
||||
| Backwards-incompatible internals change (e.g. changing things in `pocketmine\network\mcpe`) | ❌ | ✔️ | ✔️ |
|
||||
|
||||
### Notes
|
||||
- **Non-disruptive** means that usage should not be significantly altered by the change.
|
||||
- Examples of **non-disruptive** changes include adding new commands, or gameplay features like blocks and items.
|
||||
- Examples of **disruptive** changes include changing the way the server is run, world format changes (since those require downtime for the user to convert their world).
|
||||
- **API** includes all public and protected classes, functions and constants (unless marked as `@internal`).
|
||||
- Private members are not part of the API, **unless in a trait**.
|
||||
- The `pocketmine\network\mcpe` package is considered implicitly `@internal` in its entirety (see its [README](src/network/mcpe/README.md) for more details).
|
||||
- Minecraft's protocol changes are considered necessary internal changes, and are **not** subject to the same rules.
|
||||
- Protocol changes must always be released in a new minor version, since they disrupt user experience by requiring a client update.
|
||||
- BC-breaking changes to the internal network API are allowed, but only in new minor versions. This ensures that plugins which use the internal network API will not break (though they shouldn't use such API anyway).
|
||||
|
||||
## Making a pull request
|
||||
The basic procedure to create a pull request is:
|
||||
1. [Fork the repository on GitHub](https://github.com/pmmp/PocketMine-MP/fork). This gives you your own copy of the repository to make changes to.
|
||||
|
23
README.md
23
README.md
@ -1,29 +1,19 @@
|
||||
<p align="center">
|
||||
<a href="https://pmmp.io">
|
||||
<!--[if IE]>
|
||||
<img src="https://github.com/pmmp/PocketMine-MP/blob/stable/.github/readme/pocketmine.png" alt="The PocketMine-MP logo" title="PocketMine" loading="eager" />
|
||||
<![endif]-->
|
||||
<picture>
|
||||
<source srcset="https://github.com/pmmp/PocketMine-MP/raw/stable/.github/readme/pocketmine-dark.png" media="(prefers-color-scheme: dark)">
|
||||
<img src="https://github.com/pmmp/PocketMine-MP/raw/stable/.github/readme/pocketmine.png" loading="eager" />
|
||||
</picture>
|
||||
</a><br>
|
||||
<a href="https://pmmp.io"><img src="http://cdn.pocketmine.net/img/PocketMine-MP-h.png"></img></a><br>
|
||||
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/pmmp/PocketMine-MP/actions/workflows/main.yml"><img src="https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg" alt="CI" /></a>
|
||||
<a href="https://github.com/pmmp/PocketMine-MP/releases/latest"><img alt="GitHub release (latest SemVer)" src="https://img.shields.io/github/v/release/pmmp/PocketMine-MP?label=release&sort=semver"></a>
|
||||
<img src="https://github.com/pmmp/PocketMine-MP/workflows/CI/badge.svg" alt="CI" />
|
||||
<img alt="GitHub release (latest SemVer)" src="https://img.shields.io/github/v/release/pmmp/PocketMine-MP?label=release&sort=semver">
|
||||
<a href="https://hub.docker.com/r/pmmp/pocketmine-mp"><img src="https://img.shields.io/docker/v/pmmp/pocketmine-mp?logo=docker&label=image" alt="Docker image version (latest semver)" /></a>
|
||||
<a href="https://discord.gg/bmSAZBG"><img src="https://img.shields.io/discord/373199722573201408?label=discord&color=7289DA&logo=discord" alt="Discord" /></a>
|
||||
<br>
|
||||
<a href="https://github.com/pmmp/PocketMine-MP/releases"><img alt="GitHub all releases" src="https://img.shields.io/github/downloads/pmmp/PocketMine-MP/total?label=downloads%40total"></a>
|
||||
<a href="https://github.com/pmmp/PocketMine-MP/releases/latest"><img alt="GitHub release (latest by SemVer)" src="https://img.shields.io/github/downloads/pmmp/PocketMine-MP/latest/total?sort=semver"></a>
|
||||
</p>
|
||||
|
||||
## Getting started
|
||||
- [Documentation](http://pmmp.readthedocs.org/)
|
||||
- [Installation instructions](https://pmmp.readthedocs.io/en/rtfd/installation.html)
|
||||
- [Docker image](https://github.com/pmmp/PocketMine-MP/pkgs/container/pocketmine-mp)
|
||||
- [Docker image](https://hub.docker.com/r/pmmp/pocketmine-mp)
|
||||
- [Plugin repository](https://poggit.pmmp.io/plugins)
|
||||
|
||||
## Discussion/Help
|
||||
@ -34,8 +24,7 @@
|
||||
## For developers
|
||||
* [Building and running from source](BUILDING.md)
|
||||
* [Developer documentation](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
|
||||
* [Latest release API documentation](https://apidoc.pmmp.io) - Doxygen API documentation generated for each release
|
||||
* [Latest bleeding-edge API documentation](https://apidoc-dev.pmmp.io) - Doxygen API documentation generated weekly from `major-next` branch
|
||||
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
|
||||
* [DevTools](https://github.com/pmmp/DevTools/) - Development tools plugin for creating plugins
|
||||
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
|
||||
* [Contributing Guidelines](CONTRIBUTING.md)
|
||||
|
@ -7,11 +7,10 @@ GitHub is public and anyone can see the issues you post on the issue tracker, in
|
||||
|
||||
**WARNING: You may put live servers at risk by reporting a vulnerability on the GitHub issue tracker.**
|
||||
|
||||
**Contact us** by sending an email to [**security@pmmp.io**](mailto:security@pmmp.io). Include the following information:
|
||||
**Contact us** by sending an email to [**team@pmmp.io**](mailto:team@pmmp.io?subject=Security%20Vulnerability%20in%20PocketMine-MP). Include the following information:
|
||||
|
||||
- Version of PocketMine-MP
|
||||
- Detailed description of the vulnerability (e.g. how to exploit it, what the effects are)
|
||||
- Your GitHub username, if you wish to be credited for reporting the problem in the security advisory
|
||||
|
||||
Please note that we can't guarantee a reply to every email.
|
||||
|
||||
|
@ -1,128 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\generate_bedrockdata_path_consts;
|
||||
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function dirname;
|
||||
use function fclose;
|
||||
use function fopen;
|
||||
use function fwrite;
|
||||
use function is_file;
|
||||
use function scandir;
|
||||
use function str_replace;
|
||||
use function strtoupper;
|
||||
use const PHP_EOL;
|
||||
use const pocketmine\BEDROCK_DATA_PATH;
|
||||
use const SCANDIR_SORT_ASCENDING;
|
||||
use const STDERR;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
function constantify(string $permissionName) : string{
|
||||
return strtoupper(str_replace([".", "-"], "_", $permissionName));
|
||||
}
|
||||
|
||||
$files = scandir(BEDROCK_DATA_PATH, SCANDIR_SORT_ASCENDING);
|
||||
if($files === false){
|
||||
fwrite(STDERR, "Couldn't find any files in " . BEDROCK_DATA_PATH . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$consts = [];
|
||||
|
||||
foreach($files as $file){
|
||||
if($file === '.' || $file === '..'){
|
||||
continue;
|
||||
}
|
||||
if($file[0] === '.'){
|
||||
continue;
|
||||
}
|
||||
$path = Path::join(BEDROCK_DATA_PATH, $file);
|
||||
if(!is_file($path)){
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach([
|
||||
'README.md',
|
||||
'LICENSE',
|
||||
'composer.json',
|
||||
] as $ignored){
|
||||
if($file === $ignored){
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
$consts[] = $file;
|
||||
}
|
||||
|
||||
$output = fopen(dirname(__DIR__) . '/src/data/bedrock/BedrockDataFiles.php', 'wb');
|
||||
if($output === false){
|
||||
fwrite(STDERR, "Couldn't open output file" . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
fwrite($output, <<<'HEADER'
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\bedrock;
|
||||
|
||||
use const pocketmine\BEDROCK_DATA_PATH;
|
||||
|
||||
final class BedrockDataFiles{
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
|
||||
HEADER
|
||||
);
|
||||
|
||||
foreach($consts as $constName => $fileName){
|
||||
fwrite($output, "\tpublic const " . constantify($fileName) . " = BEDROCK_DATA_PATH . '/$fileName';\n");
|
||||
}
|
||||
|
||||
fwrite($output, "}\n");
|
||||
fclose($output);
|
||||
|
||||
echo "Done. Don't forget to run CS fixup after generating code.\n";
|
@ -1,197 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\generate_block_serializer_consts;
|
||||
|
||||
use pocketmine\data\bedrock\block\BlockStateData;
|
||||
use pocketmine\data\bedrock\block\BlockStateNames;
|
||||
use pocketmine\data\bedrock\block\BlockStateStringValues;
|
||||
use pocketmine\data\bedrock\block\BlockTypeNames;
|
||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||
use pocketmine\nbt\NbtException;
|
||||
use pocketmine\network\mcpe\convert\BlockStateDictionary;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Utils;
|
||||
use function array_values;
|
||||
use function asort;
|
||||
use function count;
|
||||
use function dirname;
|
||||
use function explode;
|
||||
use function fclose;
|
||||
use function file_get_contents;
|
||||
use function fopen;
|
||||
use function fwrite;
|
||||
use function is_string;
|
||||
use function ksort;
|
||||
use function mb_strtoupper;
|
||||
use function sort;
|
||||
use function strrpos;
|
||||
use function strtoupper;
|
||||
use function substr;
|
||||
use const SORT_STRING;
|
||||
use const STDERR;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
class BlockPaletteReport{
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var array<string, string>
|
||||
*/
|
||||
public array $seenTypes = [];
|
||||
/**
|
||||
* @var string[][]
|
||||
* @phpstan-var array<string, array<mixed, mixed>>
|
||||
*/
|
||||
public array $seenStateValues = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BlockStateData[] $states
|
||||
* @phpstan-param list<BlockStateData> $states
|
||||
*/
|
||||
function generateBlockPaletteReport(array $states) : BlockPaletteReport{
|
||||
$result = new BlockPaletteReport();
|
||||
|
||||
foreach($states as $stateData){
|
||||
$name = $stateData->getName();
|
||||
$result->seenTypes[$name] = $name;
|
||||
foreach(Utils::stringifyKeys($stateData->getStates()) as $k => $v){
|
||||
$result->seenStateValues[$k][$v->getValue()] = $v->getValue();
|
||||
asort($result->seenStateValues[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
ksort($result->seenTypes, SORT_STRING);
|
||||
ksort($result->seenStateValues, SORT_STRING);
|
||||
return $result;
|
||||
}
|
||||
|
||||
function constifyMcId(string $id) : string{
|
||||
return strtoupper(explode(":", $id, 2)[1]);
|
||||
}
|
||||
|
||||
function generateClassHeader(string $className) : string{
|
||||
$backslashPos = strrpos($className, "\\");
|
||||
if($backslashPos === false){
|
||||
throw new AssumptionFailedError("Expected a namespaced class FQN");
|
||||
}
|
||||
$namespace = substr($className, 0, $backslashPos);
|
||||
$shortName = substr($className, $backslashPos + 1);
|
||||
return <<<HEADER
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace $namespace;
|
||||
|
||||
/**
|
||||
* This class is generated automatically from the block palette for the current version. Do not edit it manually.
|
||||
*/
|
||||
final class $shortName{
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
|
||||
HEADER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param list<string> $seenIds
|
||||
*/
|
||||
function generateBlockIds(array $seenIds) : void{
|
||||
$output = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/block/BlockTypeNames.php', 'wb'));
|
||||
|
||||
fwrite($output, generateClassHeader(BlockTypeNames::class));
|
||||
|
||||
foreach($seenIds as $id){
|
||||
fwrite($output, "\tpublic const " . constifyMcId($id) . " = \"" . $id . "\";\n");
|
||||
}
|
||||
|
||||
fwrite($output, "}\n");
|
||||
fclose($output);
|
||||
}
|
||||
|
||||
function generateBlockStateNames(BlockPaletteReport $data) : void{
|
||||
$output = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/block/BlockStateNames.php', 'wb'));
|
||||
|
||||
fwrite($output, generateClassHeader(BlockStateNames::class));
|
||||
foreach(Utils::stringifyKeys($data->seenStateValues) as $state => $values){
|
||||
$constName = mb_strtoupper($state, 'US-ASCII');
|
||||
fwrite($output, "\tpublic const $constName = \"$state\";\n");
|
||||
}
|
||||
|
||||
fwrite($output, "}\n");
|
||||
fclose($output);
|
||||
}
|
||||
|
||||
function generateBlockStringValues(BlockPaletteReport $data) : void{
|
||||
$output = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/block/BlockStateStringValues.php', 'wb'));
|
||||
|
||||
fwrite($output, generateClassHeader(BlockStateStringValues::class));
|
||||
foreach(Utils::stringifyKeys($data->seenStateValues) as $stateName => $values){
|
||||
$anyWritten = false;
|
||||
sort($values, SORT_STRING);
|
||||
foreach($values as $value){
|
||||
if(!is_string($value)){
|
||||
continue;
|
||||
}
|
||||
$anyWritten = true;
|
||||
$constName = mb_strtoupper($stateName . "_" . $value, 'US-ASCII');
|
||||
fwrite($output, "\tpublic const $constName = \"$value\";\n");
|
||||
}
|
||||
if($anyWritten){
|
||||
fwrite($output, "\n");
|
||||
}
|
||||
}
|
||||
fwrite($output, "}\n");
|
||||
fclose($output);
|
||||
}
|
||||
|
||||
if(count($argv) !== 2){
|
||||
fwrite(STDERR, "This script regenerates BlockTypeNames, BlockStateNames and BlockStateStringValues from a given palette file\n");
|
||||
fwrite(STDERR, "Required arguments: path to block palette file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$palettePath = $argv[1];
|
||||
$paletteRaw = file_get_contents($palettePath);
|
||||
if($paletteRaw === false){
|
||||
fwrite(STDERR, "Failed to read block palette file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try{
|
||||
$states = BlockStateDictionary::loadPaletteFromString($paletteRaw);
|
||||
}catch(NbtException){
|
||||
fwrite(STDERR, "Invalid block palette file $argv[1]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$report = generateBlockPaletteReport($states);
|
||||
generateBlockIds(array_values($report->seenTypes));
|
||||
generateBlockStateNames($report);
|
||||
generateBlockStringValues($report);
|
||||
|
||||
echo "Done. Don't forget to run CS fixup after generating code.\n";
|
@ -17,28 +17,27 @@
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
if(count($argv) !== 6){
|
||||
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number> <github actions run ID>\n");
|
||||
if(count($argv) !== 5){
|
||||
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number>");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
|
||||
"base_version" => \pocketmine\VersionInfo::BASE_VERSION,
|
||||
"base_version" => \pocketmine\BASE_VERSION,
|
||||
"build" => (int) $argv[4],
|
||||
"is_dev" => \pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD,
|
||||
"channel" => \pocketmine\VersionInfo::BUILD_CHANNEL,
|
||||
"is_dev" => \pocketmine\IS_DEVELOPMENT_BUILD,
|
||||
"channel" => \pocketmine\BUILD_CHANNEL,
|
||||
"git_commit" => $argv[1],
|
||||
"mcpe_version" => \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK,
|
||||
"date" => time(), //TODO: maybe we should embed this in VersionInfo?
|
||||
"details_url" => "https://github.com/$argv[3]/releases/tag/$argv[2]",
|
||||
"download_url" => "https://github.com/$argv[3]/releases/download/$argv[2]/PocketMine-MP.phar",
|
||||
"source_url" => "https://github.com/$argv[3]/tree/$argv[2]",
|
||||
"build_log_url" => "https://github.com/$argv[3]/actions/runs/$argv[5]",
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n";
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
|
||||
|
@ -1,97 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\generate_item_serializer_ids;
|
||||
|
||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||
use pocketmine\network\mcpe\convert\ItemTypeDictionaryFromDataHelper;
|
||||
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
|
||||
use pocketmine\utils\Utils;
|
||||
use function asort;
|
||||
use function count;
|
||||
use function dirname;
|
||||
use function explode;
|
||||
use function fclose;
|
||||
use function file_get_contents;
|
||||
use function fopen;
|
||||
use function fwrite;
|
||||
use function strtoupper;
|
||||
use const SORT_STRING;
|
||||
use const STDERR;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
function constifyMcId(string $id) : string{
|
||||
return strtoupper(explode(":", $id, 2)[1]);
|
||||
}
|
||||
|
||||
function generateItemIds(ItemTypeDictionary $dictionary) : void{
|
||||
$ids = [];
|
||||
foreach($dictionary->getEntries() as $entry){
|
||||
if($entry->getNumericId() < 256){ //blockitems are serialized via BlockStateSerializer
|
||||
continue;
|
||||
}
|
||||
$ids[$entry->getStringId()] = $entry->getStringId();
|
||||
}
|
||||
asort($ids, SORT_STRING);
|
||||
|
||||
$file = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen(dirname(__DIR__) . '/src/data/bedrock/item/ItemTypeNames.php', 'wb'));
|
||||
|
||||
fwrite($file, <<<'HEADER'
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\bedrock\item;
|
||||
|
||||
/**
|
||||
* This class is generated automatically from the item type dictionary for the current version. Do not edit it manually.
|
||||
*/
|
||||
final class ItemTypeNames{
|
||||
|
||||
HEADER
|
||||
);
|
||||
|
||||
foreach(Utils::stringifyKeys($ids) as $id){
|
||||
fwrite($file, "\tpublic const " . constifyMcId($id) . " = \"" . $id . "\";\n");
|
||||
}
|
||||
fwrite($file, "}\n");
|
||||
fclose($file);
|
||||
}
|
||||
|
||||
if(count($argv) !== 2){
|
||||
fwrite(STDERR, "This script regenerates ItemTypeNames from a given item dictionary file\n");
|
||||
fwrite(STDERR, "Required argument: path to item type dictionary file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$raw = file_get_contents($argv[1]);
|
||||
if($raw === false){
|
||||
fwrite(STDERR, "Failed to read item type dictionary file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$dictionary = ItemTypeDictionaryFromDataHelper::loadFromString($raw);
|
||||
generateItemIds($dictionary);
|
||||
|
||||
echo "Done. Don't forget to run CS fixup after generating code.\n";
|
@ -1,193 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\generate_known_translation_apis;
|
||||
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\utils\Utils;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function array_map;
|
||||
use function count;
|
||||
use function dirname;
|
||||
use function file_put_contents;
|
||||
use function fwrite;
|
||||
use function implode;
|
||||
use function is_numeric;
|
||||
use function ksort;
|
||||
use function ob_get_clean;
|
||||
use function ob_start;
|
||||
use function parse_ini_file;
|
||||
use function preg_match_all;
|
||||
use function str_replace;
|
||||
use function strtoupper;
|
||||
use const INI_SCANNER_RAW;
|
||||
use const SORT_NUMERIC;
|
||||
use const SORT_STRING;
|
||||
use const STDERR;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
function constantify(string $permissionName) : string{
|
||||
return strtoupper(str_replace([".", "-"], "_", $permissionName));
|
||||
}
|
||||
|
||||
function functionify(string $permissionName) : string{
|
||||
return str_replace([".", "-"], "_", $permissionName);
|
||||
}
|
||||
|
||||
const SHARED_HEADER = <<<'HEADER'
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\lang;
|
||||
|
||||
|
||||
HEADER;
|
||||
|
||||
/**
|
||||
* @param string[] $languageDefinitions
|
||||
* @phpstan-param array<string, string> $languageDefinitions
|
||||
*/
|
||||
function generate_known_translation_keys(array $languageDefinitions) : void{
|
||||
ob_start();
|
||||
|
||||
echo SHARED_HEADER;
|
||||
echo <<<'HEADER'
|
||||
/**
|
||||
* This class contains constants for all the translations known to PocketMine-MP as per the used version of pmmp/Language.
|
||||
* This class is generated automatically, do NOT modify it by hand.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class KnownTranslationKeys{
|
||||
|
||||
HEADER;
|
||||
|
||||
ksort($languageDefinitions, SORT_STRING);
|
||||
foreach(Utils::stringifyKeys($languageDefinitions) as $k => $_){
|
||||
echo "\tpublic const ";
|
||||
echo constantify($k);
|
||||
echo " = \"" . $k . "\";\n";
|
||||
}
|
||||
|
||||
echo "}\n";
|
||||
|
||||
file_put_contents(dirname(__DIR__) . '/src/lang/KnownTranslationKeys.php', ob_get_clean());
|
||||
|
||||
echo "Done generating KnownTranslationKeys.\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $languageDefinitions
|
||||
* @phpstan-param array<string, string> $languageDefinitions
|
||||
*/
|
||||
function generate_known_translation_factory(array $languageDefinitions) : void{
|
||||
ob_start();
|
||||
|
||||
echo SHARED_HEADER;
|
||||
echo <<<'HEADER'
|
||||
/**
|
||||
* This class contains factory methods for all the translations known to PocketMine-MP as per the used version of
|
||||
* pmmp/Language.
|
||||
* This class is generated automatically, do NOT modify it by hand.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class KnownTranslationFactory{
|
||||
|
||||
HEADER;
|
||||
ksort($languageDefinitions, SORT_STRING);
|
||||
|
||||
$parameterRegex = '/{%(.+?)}/';
|
||||
|
||||
$translationContainerClass = (new \ReflectionClass(Translatable::class))->getShortName();
|
||||
foreach(Utils::stringifyKeys($languageDefinitions) as $key => $value){
|
||||
$parameters = [];
|
||||
$allParametersPositional = true;
|
||||
if(preg_match_all($parameterRegex, $value, $matches) > 0){
|
||||
foreach($matches[1] as $parameterName){
|
||||
if(is_numeric($parameterName)){
|
||||
$parameters[$parameterName] = "param$parameterName";
|
||||
}else{
|
||||
$parameters[$parameterName] = $parameterName;
|
||||
$allParametersPositional = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if($allParametersPositional){
|
||||
ksort($parameters, SORT_NUMERIC);
|
||||
}
|
||||
echo "\tpublic static function " .
|
||||
functionify($key) .
|
||||
"(" . implode(", ", array_map(fn(string $paramName) => "$translationContainerClass|string \$$paramName", $parameters)) . ") : $translationContainerClass{\n";
|
||||
echo "\t\treturn new $translationContainerClass(KnownTranslationKeys::" . constantify($key) . ", [";
|
||||
foreach($parameters as $parameterKey => $parameterName){
|
||||
echo "\n\t\t\t";
|
||||
if(!is_numeric($parameterKey)){
|
||||
echo "\"$parameterKey\"";
|
||||
}else{
|
||||
echo $parameterKey;
|
||||
}
|
||||
echo " => \$$parameterName,";
|
||||
}
|
||||
if(count($parameters) !== 0){
|
||||
echo "\n\t\t";
|
||||
}
|
||||
echo "]);\n\t}\n\n";
|
||||
}
|
||||
|
||||
echo "}\n";
|
||||
|
||||
file_put_contents(dirname(__DIR__) . '/src/lang/KnownTranslationFactory.php', ob_get_clean());
|
||||
|
||||
echo "Done generating KnownTranslationFactory.\n";
|
||||
}
|
||||
|
||||
$lang = parse_ini_file(Path::join(\pocketmine\LOCALE_DATA_PATH, "eng.ini"), false, INI_SCANNER_RAW);
|
||||
if($lang === false){
|
||||
fwrite(STDERR, "Missing language files!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
generate_known_translation_keys($lang);
|
||||
generate_known_translation_factory($lang);
|
@ -1,132 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\update_registry_annotations;
|
||||
|
||||
use function basename;
|
||||
use function class_exists;
|
||||
use function count;
|
||||
use function dirname;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function fwrite;
|
||||
use function implode;
|
||||
use function is_dir;
|
||||
use function ksort;
|
||||
use function mb_strtoupper;
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
use function str_ends_with;
|
||||
use function str_replace;
|
||||
use const SORT_STRING;
|
||||
use const STDERR;
|
||||
|
||||
if(count($argv) !== 2){
|
||||
fwrite(STDERR, "Provide a path to process\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object[] $members
|
||||
*/
|
||||
function generateMethodAnnotations(string $namespaceName, array $members) : string{
|
||||
$selfName = basename(__FILE__);
|
||||
$lines = ["/**"];
|
||||
$lines[] = " * This doc-block is generated automatically, do not modify it manually.";
|
||||
$lines[] = " * This must be regenerated whenever registry members are added, removed or changed.";
|
||||
$lines[] = " * @see build/$selfName";
|
||||
$lines[] = " * @generate-registry-docblock";
|
||||
$lines[] = " *";
|
||||
|
||||
static $lineTmpl = " * @method static %2\$s %s()";
|
||||
$memberLines = [];
|
||||
foreach($members as $name => $member){
|
||||
$reflect = new \ReflectionClass($member);
|
||||
while($reflect !== false && $reflect->isAnonymous()){
|
||||
$reflect = $reflect->getParentClass();
|
||||
}
|
||||
if($reflect === false){
|
||||
$typehint = "object";
|
||||
}elseif($reflect->getNamespaceName() === $namespaceName){
|
||||
$typehint = $reflect->getShortName();
|
||||
}else{
|
||||
$typehint = '\\' . $reflect->getName();
|
||||
}
|
||||
$accessor = mb_strtoupper($name);
|
||||
$memberLines[$accessor] = sprintf($lineTmpl, $accessor, $typehint);
|
||||
}
|
||||
ksort($memberLines, SORT_STRING);
|
||||
|
||||
foreach($memberLines as $line){
|
||||
$lines[] = $line;
|
||||
}
|
||||
$lines[] = " */";
|
||||
return implode("\n", $lines);
|
||||
}
|
||||
|
||||
function processFile(string $file) : void{
|
||||
$contents = file_get_contents($file);
|
||||
if($contents === false){
|
||||
throw new \RuntimeException("Failed to get contents of $file");
|
||||
}
|
||||
|
||||
if(preg_match("/(*ANYCRLF)^namespace (.+);$/m", $contents, $matches) !== 1 || preg_match('/(*ANYCRLF)^((final|abstract)\s+)?class /m', $contents) !== 1){
|
||||
return;
|
||||
}
|
||||
$shortClassName = basename($file, ".php");
|
||||
$className = $matches[1] . "\\" . $shortClassName;
|
||||
if(!class_exists($className)){
|
||||
return;
|
||||
}
|
||||
$reflect = new \ReflectionClass($className);
|
||||
$docComment = $reflect->getDocComment();
|
||||
if($docComment === false || preg_match("/(*ANYCRLF)^\s*\*\s*@generate-registry-docblock$/m", $docComment) !== 1){
|
||||
return;
|
||||
}
|
||||
echo "Found registry in $file\n";
|
||||
|
||||
$replacement = generateMethodAnnotations($matches[1], $className::getAll());
|
||||
|
||||
$newContents = str_replace($docComment, $replacement, $contents);
|
||||
if($newContents !== $contents){
|
||||
echo "Writing changed file $file\n";
|
||||
file_put_contents($file, $newContents);
|
||||
}else{
|
||||
echo "No changes made to file $file\n";
|
||||
}
|
||||
}
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
if(is_dir($argv[1])){
|
||||
/** @var string $file */
|
||||
foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1], \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME)) as $file){
|
||||
if(!str_ends_with($file, ".php")){
|
||||
continue;
|
||||
}
|
||||
|
||||
processFile($file);
|
||||
}
|
||||
}else{
|
||||
processFile($argv[1]);
|
||||
}
|
@ -1,263 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\generate_runtime_enum_serializers;
|
||||
|
||||
use pocketmine\block\utils\BellAttachmentType;
|
||||
use pocketmine\block\utils\CopperOxidation;
|
||||
use pocketmine\block\utils\CoralType;
|
||||
use pocketmine\block\utils\DirtType;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\block\utils\FroglightType;
|
||||
use pocketmine\block\utils\LeverFacing;
|
||||
use pocketmine\block\utils\MobHeadType;
|
||||
use pocketmine\block\utils\MushroomBlockType;
|
||||
use pocketmine\block\utils\SlabType;
|
||||
use pocketmine\item\MedicineType;
|
||||
use pocketmine\item\PotionType;
|
||||
use pocketmine\item\SuspiciousStewType;
|
||||
use function array_key_first;
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function ceil;
|
||||
use function count;
|
||||
use function dirname;
|
||||
use function file_put_contents;
|
||||
use function implode;
|
||||
use function ksort;
|
||||
use function lcfirst;
|
||||
use function log;
|
||||
use function ob_get_clean;
|
||||
use function ob_start;
|
||||
use const SORT_STRING;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* @param string[] $memberNames
|
||||
* @phpstan-param list<string> $memberNames
|
||||
*
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
function buildWriterFunc(string $virtualTypeName, string $nativeTypeName, array $memberNames, string $functionName) : array{
|
||||
$bits = getBitsRequired($memberNames);
|
||||
$lines = [];
|
||||
|
||||
$lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{";
|
||||
$lines[] = "\t\$this->writeInt($bits, match(\$value){";
|
||||
|
||||
foreach($memberNames as $key => $memberName){
|
||||
$lines[] = "\t\t$memberName => $key,";
|
||||
}
|
||||
$lines[] = "\t\tdefault => throw new \pocketmine\utils\AssumptionFailedError(\"All $virtualTypeName cases should be covered\")";
|
||||
$lines[] = "\t});";
|
||||
$lines[] = "}";
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $memberNames
|
||||
* @phpstan-param list<string> $memberNames
|
||||
*
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
function buildReaderFunc(string $virtualTypeName, string $nativeTypeName, array $memberNames, string $functionName) : array{
|
||||
$bits = getBitsRequired($memberNames);
|
||||
$lines = [];
|
||||
|
||||
$lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{";
|
||||
$lines[] = "\t\$value = match(\$this->readInt($bits)){";
|
||||
|
||||
foreach($memberNames as $key => $memberName){
|
||||
$lines[] = "\t\t$key => $memberName,";
|
||||
}
|
||||
$lines[] = "\t\tdefault => throw new InvalidSerializedRuntimeDataException(\"Invalid serialized value for $virtualTypeName\")";
|
||||
$lines[] = "\t};";
|
||||
$lines[] = "}";
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
function buildInterfaceFunc(string $nativeTypeName, string $functionName) : string{
|
||||
return "public function $functionName(\\$nativeTypeName &\$value) : void;";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $memberNames
|
||||
* @phpstan-param list<string> $memberNames
|
||||
*
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
function buildSizeCalculationFunc(string $nativeTypeName, string $functionName, array $memberNames) : array{
|
||||
$lines = [];
|
||||
$lines[] = "public function $functionName(\\$nativeTypeName &\$value) : void{";
|
||||
$lines[] = "\t\$this->addBits(" . getBitsRequired($memberNames) . ");";
|
||||
$lines[] = "}";
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $members
|
||||
*/
|
||||
function getBitsRequired(array $members) : int{
|
||||
return (int) ceil(log(count($members), 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object[] $members
|
||||
* @phpstan-param array<string, object> $members
|
||||
*
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
function stringifyEnumMembers(array $members, string $enumClass) : array{
|
||||
ksort($members, SORT_STRING);
|
||||
return array_map(fn(string $enumCaseName) => "\\$enumClass::$enumCaseName()", array_keys($members));
|
||||
}
|
||||
|
||||
$enumsUsed = [
|
||||
BellAttachmentType::getAll(),
|
||||
CopperOxidation::getAll(),
|
||||
CoralType::getAll(),
|
||||
DirtType::getAll(),
|
||||
DyeColor::getAll(),
|
||||
FroglightType::getAll(),
|
||||
LeverFacing::getAll(),
|
||||
MedicineType::getAll(),
|
||||
MushroomBlockType::getAll(),
|
||||
MobHeadType::getAll(),
|
||||
SlabType::getAll(),
|
||||
SuspiciousStewType::getAll(),
|
||||
PotionType::getAll()
|
||||
];
|
||||
|
||||
$readerFuncs = [
|
||||
"" => [
|
||||
"abstract protected function readInt(int \$bits) : int;"
|
||||
]
|
||||
];
|
||||
$writerFuncs = [
|
||||
"" => [
|
||||
"abstract protected function writeInt(int \$bits, int \$value) : void;"
|
||||
]
|
||||
];
|
||||
$interfaceFuncs = [];
|
||||
$sizeCalculationFuncs = [
|
||||
"" => [
|
||||
"abstract protected function addBits(int \$bits) : void;"
|
||||
]
|
||||
];
|
||||
|
||||
foreach($enumsUsed as $enumMembers){
|
||||
if(count($enumMembers) === 0){
|
||||
throw new \InvalidArgumentException("Enum members cannot be empty");
|
||||
}
|
||||
$reflect = new \ReflectionClass($enumMembers[array_key_first($enumMembers)]);
|
||||
$virtualTypeName = $reflect->getShortName();
|
||||
$nativeTypeName = $reflect->getName();
|
||||
$functionName = lcfirst($virtualTypeName);
|
||||
|
||||
$stringifiedMembers = stringifyEnumMembers($enumMembers, $nativeTypeName);
|
||||
$writerFuncs[$functionName] = buildWriterFunc(
|
||||
$virtualTypeName,
|
||||
$nativeTypeName,
|
||||
$stringifiedMembers,
|
||||
$functionName
|
||||
);
|
||||
$readerFuncs[$functionName] = buildReaderFunc(
|
||||
$virtualTypeName,
|
||||
$nativeTypeName,
|
||||
$stringifiedMembers,
|
||||
$functionName
|
||||
);
|
||||
$interfaceFuncs[$functionName] = [buildInterfaceFunc(
|
||||
$nativeTypeName,
|
||||
$functionName
|
||||
)];
|
||||
$sizeCalculationFuncs[$functionName] = buildSizeCalculationFunc(
|
||||
$nativeTypeName,
|
||||
$functionName,
|
||||
$stringifiedMembers
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[][] $functions
|
||||
* @phpstan-param array<string, list<string>> $functions
|
||||
*/
|
||||
function printFunctions(array $functions, string $className, string $classType) : void{
|
||||
ksort($functions, SORT_STRING);
|
||||
|
||||
ob_start();
|
||||
|
||||
echo <<<'HEADER'
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\runtime;
|
||||
|
||||
/**
|
||||
* This class is auto-generated. Do not edit it manually.
|
||||
* @see build/generate-runtime-enum-serializers.php
|
||||
*/
|
||||
|
||||
HEADER;
|
||||
|
||||
echo "$classType $className{\n\n";
|
||||
echo implode("\n\n", array_map(fn(array $functionLines) => "\t" . implode("\n\t", $functionLines), $functions));
|
||||
echo "\n\n}\n";
|
||||
|
||||
file_put_contents(dirname(__DIR__) . '/src/data/runtime/' . $className . '.php', ob_get_clean());
|
||||
}
|
||||
|
||||
printFunctions($writerFuncs, "RuntimeEnumSerializerTrait", "trait");
|
||||
printFunctions($readerFuncs, "RuntimeEnumDeserializerTrait", "trait");
|
||||
printFunctions($interfaceFuncs, "RuntimeEnumDescriber", "interface");
|
||||
printFunctions($sizeCalculationFuncs, "RuntimeEnumSizeCalculatorTrait", "trait");
|
||||
|
||||
echo "Done. Don't forget to run CS fixup after generating code.\n";
|
@ -17,32 +17,31 @@
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\make_release;
|
||||
|
||||
use pocketmine\utils\Filesystem;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use pocketmine\VersionInfo;
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function dirname;
|
||||
use function fgets;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function fwrite;
|
||||
use function getopt;
|
||||
use function is_string;
|
||||
use function max;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
use function sleep;
|
||||
use function sprintf;
|
||||
use function str_pad;
|
||||
use function strlen;
|
||||
use function strtolower;
|
||||
use function system;
|
||||
use const pocketmine\BASE_VERSION;
|
||||
use const pocketmine\BUILD_CHANNEL;
|
||||
use const STDERR;
|
||||
use const STDIN;
|
||||
use const STDOUT;
|
||||
@ -51,7 +50,7 @@ use const STR_PAD_LEFT;
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{
|
||||
$versionInfo = Filesystem::fileGetContents($versionInfoPath);
|
||||
$versionInfo = file_get_contents($versionInfoPath);
|
||||
$versionInfo = preg_replace(
|
||||
$pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
|
||||
'$1const BASE_VERSION = "' . $newVersion . '";',
|
||||
@ -76,17 +75,9 @@ const ACCEPTED_OPTS = [
|
||||
"channel" => "Release channel to post this build into"
|
||||
];
|
||||
|
||||
function systemWrapper(string $command, string $errorMessage) : void{
|
||||
system($command, $result);
|
||||
if($result !== 0){
|
||||
echo "error: $errorMessage; aborting\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function main() : void{
|
||||
$filteredOpts = [];
|
||||
foreach(Utils::stringifyKeys(getopt("", ["current:", "next:", "channel:", "help"])) as $optName => $optValue){
|
||||
foreach(getopt("", ["current:", "next:", "channel:", "help"]) as $optName => $optValue){
|
||||
if($optName === "help"){
|
||||
fwrite(STDOUT, "Options:\n");
|
||||
|
||||
@ -103,62 +94,43 @@ function main() : void{
|
||||
$filteredOpts[$optName] = $optValue;
|
||||
}
|
||||
|
||||
$channel = $filteredOpts["channel"] ?? null;
|
||||
if(isset($filteredOpts["current"])){
|
||||
$currentVer = new VersionString($filteredOpts["current"]);
|
||||
}else{
|
||||
$currentVer = new VersionString(VersionInfo::BASE_VERSION);
|
||||
$currentVer = new VersionString(BASE_VERSION);
|
||||
}
|
||||
|
||||
$nextVer = isset($filteredOpts["next"]) ? new VersionString($filteredOpts["next"]) : null;
|
||||
|
||||
$suffix = $currentVer->getSuffix();
|
||||
if($suffix !== ""){
|
||||
if($channel === "stable"){
|
||||
fwrite(STDERR, "error: cannot release a suffixed build into the stable channel\n");
|
||||
exit(1);
|
||||
}
|
||||
if(preg_match('/^([A-Za-z]+)(\d+)$/', $suffix, $matches) !== 1){
|
||||
echo "error: invalid current version suffix \"$suffix\"; aborting\n";
|
||||
exit(1);
|
||||
}
|
||||
$nextVer ??= new VersionString(sprintf(
|
||||
"%u.%u.%u-%s%u",
|
||||
$currentVer->getMajor(),
|
||||
$currentVer->getMinor(),
|
||||
$currentVer->getPatch(),
|
||||
$matches[1],
|
||||
((int) $matches[2]) + 1
|
||||
));
|
||||
$channel ??= strtolower($matches[1]);
|
||||
if(isset($filteredOpts["next"])){
|
||||
$nextVer = new VersionString($filteredOpts["next"]);
|
||||
}else{
|
||||
$nextVer ??= new VersionString(sprintf(
|
||||
$nextVer = new VersionString(sprintf(
|
||||
"%u.%u.%u",
|
||||
$currentVer->getMajor(),
|
||||
$currentVer->getMinor(),
|
||||
$currentVer->getPatch() + 1
|
||||
));
|
||||
$channel ??= "stable";
|
||||
}
|
||||
$channel = $filteredOpts["channel"] ?? BUILD_CHANNEL;
|
||||
|
||||
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
|
||||
echo "$currentVer will be published on release channel \"$channel\".\n";
|
||||
echo "please add appropriate notes to the changelog and press enter...";
|
||||
fgets(STDIN);
|
||||
systemWrapper('git add "' . dirname(__DIR__) . '/changelogs"', "failed to stage changelog changes");
|
||||
system('git add "' . dirname(__DIR__) . '/changelogs"');
|
||||
system('git diff --cached --quiet "' . dirname(__DIR__) . '/changelogs"', $result);
|
||||
if($result === 0){
|
||||
echo "error: no changelog changes detected; aborting\n";
|
||||
exit(1);
|
||||
}
|
||||
$versionInfoPath = dirname(__DIR__) . '/src/VersionInfo.php';
|
||||
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false, $channel);
|
||||
systemWrapper('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"', "failed to create release commit");
|
||||
systemWrapper('git tag ' . $currentVer->getBaseVersion(), "failed to create release tag");
|
||||
|
||||
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
|
||||
system('git tag ' . $currentVer->getBaseVersion());
|
||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true, $channel);
|
||||
systemWrapper('git add "' . $versionInfoPath . '"', "failed to stage changes for post-release commit");
|
||||
systemWrapper('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"', "failed to create post-release commit");
|
||||
system('git add "' . $versionInfoPath . '"');
|
||||
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
|
||||
echo "pushing changes in 5 seconds\n";
|
||||
sleep(5);
|
||||
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
||||
}
|
||||
|
||||
main();
|
||||
|
Submodule build/php updated: fcbc15f23e...bd329dba08
1
build/preprocessor
Submodule
1
build/preprocessor
Submodule
Submodule build/preprocessor added at 1b9304de61
@ -17,7 +17,7 @@
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
@ -40,13 +40,12 @@ use function rtrim;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function unlink;
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const PHP_EOL;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* @param string[] $strings
|
||||
* @param string[] $strings
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
@ -151,7 +150,6 @@ function main() : void{
|
||||
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
|
||||
dirname(__DIR__) . DIRECTORY_SEPARATOR,
|
||||
[
|
||||
'resources',
|
||||
'src',
|
||||
'vendor'
|
||||
],
|
||||
@ -170,7 +168,7 @@ if(!is_readable($tmpDir) or !is_writable($tmpDir)){
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require("phar://" . __FILE__ . "/src/PocketMine.php");
|
||||
require("phar://" . __FILE__ . "/src/pocketmine/PocketMine.php");
|
||||
__HALT_COMPILER();
|
||||
STUB
|
||||
,
|
||||
|
10
changelogs/3.28.md
Normal file
10
changelogs/3.28.md
Normal file
@ -0,0 +1,10 @@
|
||||
**For Minecraft: Bedrock Edition 1.18.10**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 3.28.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.18.10.
|
File diff suppressed because it is too large
Load Diff
1651
changelogs/4.0.md
1651
changelogs/4.0.md
File diff suppressed because it is too large
Load Diff
@ -1,166 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.18.0**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.1.0-BETA1
|
||||
Released 22nd January 2022.
|
||||
|
||||
## General
|
||||
- Game mode names (e.g. `survival`, `creative`) may now be used for the `gamemode` property in `server.properties`.
|
||||
- Increased default maximum render distance to 16 chunks. Players with a render distance smaller than this will notice no difference.
|
||||
- The setup wizard now prompts for a maximum render distance value.
|
||||
- The setup wizard now prompts for an IPv6 port selection. Previously it would always use 19133.
|
||||
- `chunk-ticking.disable-block-ticking` now accepts block names like those used in the `/give` command.
|
||||
- The `/clear` command now behaves more like vanilla:
|
||||
- The order of inventories is now the same as Bedrock.
|
||||
- The cursor and offhand inventories are now cleared if necessary.
|
||||
|
||||
## Technical
|
||||
- `PlayerAuthInputPacket` is now used instead of `MovePlayerPacket` for processing movements. This improves position and rotation accuracy.
|
||||
- `&&` and `||` are now always used instead of `and` and `or`.
|
||||
- New version of `pocketmine/errorhandler` is used by this version, adding support for `ErrorToExceptionHandler::trap()`. This enables reliably capturing `E_WARNING` and `E_NOTICE` from functions such as `yaml_parse()` and friends.
|
||||
- New dependency versions are required by this version:
|
||||
- `pocketmine/bedrock-protocol` has been updated from 7.1.0 to [7.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/7.3.0%2Bbedrock-1.18.0).
|
||||
- `pocketmine/errorhandler` has been updated from 0.3.0 to [0.6.0](https://github.com/pmmp/ErrorHandler/releases/tag/0.6.0).
|
||||
|
||||
## API
|
||||
### Block
|
||||
- The following classes have been added:
|
||||
- `Lectern`
|
||||
- `Pumpkin`
|
||||
- The following public API methods have been added:
|
||||
- `Block->getTypeId() : int` - returns an integer which uniquely identifies the block type, ignoring things like facing, colour etc.
|
||||
- `VanillaBlocks::LECTERN()`
|
||||
|
||||
### Entity
|
||||
- The following classes have been added:
|
||||
- `animation\ItemEntityStackSizeChangeAnimation`
|
||||
- The following public API methods have been added:
|
||||
- `object\ItemEntity->isMergeable(object\ItemEntity $other) : bool`
|
||||
- `object\ItemEntity->setStackSize(int $size) : void`
|
||||
- `object\ItemEntity->tryMergeInto(object\ItemEntity $other) : bool`
|
||||
- `ExperienceManager->canAttractXpOrbs() : bool`
|
||||
- `ExperienceManager->setCanAttractXpOrbs(bool $v = true) : void`
|
||||
- `Entity->getSize() : EntitySizeInfo`
|
||||
- `Living->isGliding() : bool`
|
||||
- `Living->isSwimming() : bool`
|
||||
- `Living->setGliding(bool $value = true) : void`
|
||||
- `Living->setSwimming(bool $value = true) : void`
|
||||
- The following protected API methods have been added:
|
||||
- `Entity->getBlocksIntersected(float $inset) : \Generator<int, Block, void, void>`
|
||||
|
||||
### Event
|
||||
- `BlockSpreadEvent` is now called when fire spreads to the positions of blocks it burns away.
|
||||
- `BlockFormEvent` is now called when concrete powder turns into concrete due to contact with water.
|
||||
- The following classes have been added:
|
||||
- `BlockMeltEvent` - called when ice or snow melts
|
||||
- `ChestPairEvent` - called when two chests try to form a pair
|
||||
- `PlayerToggleGlideEvent` - called when a player starts or stops gliding
|
||||
- `PlayerToggleSwimEvent` - called when a player starts or stops swimming
|
||||
|
||||
### Item
|
||||
- The following public API methods have been added:
|
||||
- `SplashPotion->getType() : PotionType`
|
||||
- `VanillaItems::AIR()`
|
||||
- The following API methods have been deprecated:
|
||||
- `ItemFactory::air()` - use `VanillaItems::AIR()` instead
|
||||
|
||||
### Player
|
||||
- The following public API methods have been added:
|
||||
- `Player->hasBlockCollision() : bool`
|
||||
- `Player->setHasBlockCollision(bool $value)` - allows controlling spectator-like no-clip behaviour without changing game mode
|
||||
- `Player->toggleSwim(bool $swim) : bool` - called by the network system when the client tries to start/stop swimming
|
||||
- `Player->toggleGlide(bool $glide) : bool` - called by the network system when the client tries to start/stop gliding
|
||||
|
||||
### Server
|
||||
- The following public API constants have been added:
|
||||
- `Server::DEFAULT_SERVER_NAME`
|
||||
- `Server::DEFAULT_MAX_PLAYERS`
|
||||
- `Server::DEFAULT_PORT_IPV4`
|
||||
- `Server::DEFAULT_PORT_IPV6`
|
||||
- `Server::DEFAULT_MAX_VIEW_DISTANCE`
|
||||
|
||||
### Utils
|
||||
- Config parsing errors are now always represented by `ConfigLoadException` and include the path to the file in the message.
|
||||
- Added `TextFormat::MINECOIN_GOLD`, and support for it to the various `TextFormat` methods.
|
||||
- The following public API methods have been added:
|
||||
- `Utils::assumeNotFalse()` - static analysis crutch to silence PHPStan errors without using `ignoreErrors` or `@phpstan-ignore-line`, which are both too coarse.
|
||||
- The following public API properties have been added:
|
||||
- `Terminal::$COLOR_MINECOIN_GOLD`
|
||||
- The following classes have been added:
|
||||
- `ConfigLoadException`
|
||||
- Fixed `Random->nextSignedInt()` to actually return a signed int. Previously it would return any integer value between 0 and 4,294,957,295.
|
||||
- Fixed `Random->nextSignedFloat()` to return a float between `-1.0` and `1.0`. Previously it would return any value between `0.0` and `2.0`.
|
||||
- `VersionString->getNumber()` output is now structured differently to fix overflow issues caused by the old format.
|
||||
|
||||
### World
|
||||
- The following classes have been added:
|
||||
- `sound\ItemUseOnBlockSound`
|
||||
- `sound\LecternPlaceBookSound`
|
||||
|
||||
## Gameplay
|
||||
### Blocks
|
||||
- Fire now spreads.
|
||||
- Implemented lectern blocks.
|
||||
- Added missing sounds for hoeing grass and dirt.
|
||||
- Added missing sounds for using a shovel on grass to create grass path.
|
||||
- Pumpkins can now be carved using shears.
|
||||
|
||||
### Items
|
||||
- Dropped items of the same type now merge with each other.
|
||||
|
||||
### Misc
|
||||
- Implemented player swimming.
|
||||
|
||||
# 4.1.0-BETA2
|
||||
Released 27th January 2022.
|
||||
|
||||
## API
|
||||
### Block
|
||||
- The following API methods have been added:
|
||||
- `utils\BrewingStandSlot->getSlotNumber() : int`
|
||||
- `utils\FurnaceType->getCookSound() : Sound`
|
||||
- The following API constants have been added:
|
||||
- `tile\BrewingStand::BREW_TIME_TICKS`
|
||||
|
||||
### Crafting
|
||||
- The following API methods have been added:
|
||||
- `CraftingManager->getPotionContainerChangeRecipes() : array<int, array<string, PotionContainerChangeRecipe>>`
|
||||
- `CraftingManager->getPotionTypeRecipes() : array<string, array<string, PotionTypeRecipe>>`
|
||||
- `CraftingManager->registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void`
|
||||
- `CraftingManager->registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void`
|
||||
- The following classes have been added:
|
||||
- `BrewingRecipe`
|
||||
- `PotionContainerChangeRecipe`
|
||||
- `PotionTypeRecipe`
|
||||
|
||||
### Event
|
||||
- The following classes have been added:
|
||||
- `BrewItemEvent` - called when a brewing stand finishes brewing potions; this is called up to 3 times (once for each brewing slot, as needed)
|
||||
- `BrewingFuelUseEvent` - called when a brewing stand consumes blaze powder
|
||||
- `PlayerViewDistanceChangeEvent` - called whenever a player alters their render distance or requests one for the first time when connecting
|
||||
|
||||
### World
|
||||
#### Sound
|
||||
- The following classes have been added:
|
||||
- `BlastFurnaceSound` - the sound made by a blast furnace during smelting
|
||||
- `FurnaceSound` - the sound made by a regular furnace during cooking or smelting
|
||||
- `PotionFinishBrewingSound` - the sound made by a brewing stand when a potion finishes being brewed
|
||||
- `SmokerSound` - the sound made by a smoker during cooking
|
||||
|
||||
## Gameplay
|
||||
### Blocks
|
||||
- Brewing stands can now be used for brewing potions.
|
||||
- The visual appearance of a brewing stand now updates correctly when the contents of its inventory changes (adding/removing potions).
|
||||
- Added missing sounds for furnace, blast furnace and smoker.
|
||||
- Fixed ender chest not dropping itself when mined with a Silk Touch pickaxe.
|
||||
- Cobwebs now drop themselves when mined using shears.
|
||||
- The correct amount of fall damage is now taken when falling from a height onto hay bales.
|
||||
- Fixed block updating bug introduced by beta1 which caused crops and other plants to never grow.
|
||||
|
||||
### Misc
|
||||
- Added a workaround for client hitbox size bug after swimming which caused the player to be able to fit into one-block-tall gaps.
|
@ -1,142 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.18.0**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.1.0
|
||||
Released 7th February 2022.
|
||||
|
||||
## General
|
||||
- Game mode names (e.g. `survival`, `creative`) may now be used for the `gamemode` property in `server.properties`.
|
||||
- Increased default maximum render distance to 16 chunks. Players with a render distance smaller than this will notice no difference.
|
||||
- The setup wizard now prompts for a maximum render distance value.
|
||||
- The setup wizard now prompts for an IPv6 port selection. Previously it would always use 19133.
|
||||
- `chunk-ticking.disable-block-ticking` now accepts block names like those used in the `/give` command.
|
||||
- The `/clear` command now behaves more like vanilla:
|
||||
- The order of inventories is now the same as Bedrock.
|
||||
- The cursor and offhand inventories are now cleared if necessary.
|
||||
|
||||
## Technical
|
||||
- `PlayerAuthInputPacket` is now used instead of `MovePlayerPacket` for processing movements. This improves position and rotation accuracy.
|
||||
- `&&` and `||` are now always used instead of `and` and `or`.
|
||||
- New version of `pocketmine/errorhandler` is used by this version, adding support for `ErrorToExceptionHandler::trap()`. This enables reliably capturing `E_WARNING` and `E_NOTICE` from functions such as `yaml_parse()` and friends.
|
||||
- New dependency versions are required by this version:
|
||||
- `pocketmine/bedrock-protocol` has been updated from 7.1.0 to [7.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/7.3.0%2Bbedrock-1.18.0).
|
||||
- `pocketmine/errorhandler` has been updated from 0.3.0 to [0.6.0](https://github.com/pmmp/ErrorHandler/releases/tag/0.6.0).
|
||||
|
||||
## API
|
||||
### Block
|
||||
- The following classes have been added:
|
||||
- `Lectern`
|
||||
- `Pumpkin`
|
||||
- The following public API methods have been added:
|
||||
- `Block->getTypeId() : int` - returns an integer which uniquely identifies the block type, ignoring things like facing, colour etc.
|
||||
- `VanillaBlocks::LECTERN()`
|
||||
- `utils\BrewingStandSlot->getSlotNumber() : int`
|
||||
- `utils\FurnaceType->getCookSound() : Sound`
|
||||
- The following API constants have been added:
|
||||
- `tile\BrewingStand::BREW_TIME_TICKS`
|
||||
|
||||
### Crafting
|
||||
- The following API methods have been added:
|
||||
- `CraftingManager->getPotionContainerChangeRecipes() : array<int, array<string, PotionContainerChangeRecipe>>`
|
||||
- `CraftingManager->getPotionTypeRecipes() : array<string, array<string, PotionTypeRecipe>>`
|
||||
- `CraftingManager->registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void`
|
||||
- `CraftingManager->registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void`
|
||||
- The following classes have been added:
|
||||
- `BrewingRecipe`
|
||||
- `PotionContainerChangeRecipe`
|
||||
- `PotionTypeRecipe`
|
||||
|
||||
### Entity
|
||||
- The following classes have been added:
|
||||
- `animation\ItemEntityStackSizeChangeAnimation`
|
||||
- The following public API methods have been added:
|
||||
- `object\ItemEntity->isMergeable(object\ItemEntity $other) : bool`
|
||||
- `object\ItemEntity->setStackSize(int $size) : void`
|
||||
- `object\ItemEntity->tryMergeInto(object\ItemEntity $other) : bool`
|
||||
- `ExperienceManager->canAttractXpOrbs() : bool`
|
||||
- `ExperienceManager->setCanAttractXpOrbs(bool $v = true) : void`
|
||||
- `Entity->getSize() : EntitySizeInfo`
|
||||
- `Living->isGliding() : bool`
|
||||
- `Living->isSwimming() : bool`
|
||||
- `Living->setGliding(bool $value = true) : void`
|
||||
- `Living->setSwimming(bool $value = true) : void`
|
||||
- The following protected API methods have been added:
|
||||
- `Entity->getBlocksIntersected(float $inset) : \Generator<int, Block, void, void>`
|
||||
|
||||
### Event
|
||||
- `BlockSpreadEvent` is now called when fire spreads to the positions of blocks it burns away.
|
||||
- `BlockFormEvent` is now called when concrete powder turns into concrete due to contact with water.
|
||||
- The following classes have been added:
|
||||
- `BlockMeltEvent` - called when ice or snow melts
|
||||
- `BrewItemEvent` - called when a brewing stand finishes brewing potions; this is called up to 3 times (once for each brewing slot, as needed)
|
||||
- `BrewingFuelUseEvent` - called when a brewing stand consumes blaze powder
|
||||
- `ChestPairEvent` - called when two chests try to form a pair
|
||||
- `PlayerToggleGlideEvent` - called when a player starts or stops gliding
|
||||
- `PlayerToggleSwimEvent` - called when a player starts or stops swimming
|
||||
- `PlayerViewDistanceChangeEvent` - called whenever a player alters their render distance or requests one for the first time when connecting
|
||||
|
||||
### Item
|
||||
- The following public API methods have been added:
|
||||
- `SplashPotion->getType() : PotionType`
|
||||
- `VanillaItems::AIR()`
|
||||
- The following API methods have been deprecated:
|
||||
- `ItemFactory::air()` - use `VanillaItems::AIR()` instead
|
||||
|
||||
### Player
|
||||
- The following public API methods have been added:
|
||||
- `Player->hasBlockCollision() : bool`
|
||||
- `Player->setHasBlockCollision(bool $value)` - allows controlling spectator-like no-clip behaviour without changing game mode
|
||||
- `Player->toggleSwim(bool $swim) : bool` - called by the network system when the client tries to start/stop swimming
|
||||
- `Player->toggleGlide(bool $glide) : bool` - called by the network system when the client tries to start/stop gliding
|
||||
|
||||
### Server
|
||||
- The following public API constants have been added:
|
||||
- `Server::DEFAULT_SERVER_NAME`
|
||||
- `Server::DEFAULT_MAX_PLAYERS`
|
||||
- `Server::DEFAULT_PORT_IPV4`
|
||||
- `Server::DEFAULT_PORT_IPV6`
|
||||
- `Server::DEFAULT_MAX_VIEW_DISTANCE`
|
||||
|
||||
### Utils
|
||||
- Config parsing errors are now always represented by `ConfigLoadException` and include the path to the file in the message.
|
||||
- Added `TextFormat::MINECOIN_GOLD`, and support for it to the various `TextFormat` methods.
|
||||
- The following public API methods have been added:
|
||||
- `Utils::assumeNotFalse()` - static analysis crutch to silence PHPStan errors without using `ignoreErrors` or `@phpstan-ignore-line`, which are both too coarse.
|
||||
- The following public API properties have been added:
|
||||
- `Terminal::$COLOR_MINECOIN_GOLD`
|
||||
- The following classes have been added:
|
||||
- `ConfigLoadException`
|
||||
- Fixed `Random->nextSignedInt()` to actually return a signed int. Previously it would return any integer value between 0 and 4,294,957,295.
|
||||
- Fixed `Random->nextSignedFloat()` to return a float between `-1.0` and `1.0`. Previously it would return any value between `0.0` and `2.0`.
|
||||
- `VersionString->getNumber()` output is now structured differently to fix overflow issues caused by the old format.
|
||||
|
||||
### World
|
||||
- The following classes have been added:
|
||||
- `sound\BlastFurnaceSound` - the sound made by a blast furnace during smelting
|
||||
- `sound\FurnaceSound` - the sound made by a regular furnace during cooking or smelting
|
||||
- `sound\ItemUseOnBlockSound`
|
||||
- `sound\LecternPlaceBookSound`
|
||||
- `sound\PotionFinishBrewingSound` - the sound made by a brewing stand when a potion finishes being brewed
|
||||
- `sound\SmokerSound` - the sound made by a smoker during cooking
|
||||
|
||||
## Gameplay
|
||||
### Blocks
|
||||
- Fire now spreads.
|
||||
- Implemented lectern blocks.
|
||||
- Added missing sounds for hoeing grass and dirt.
|
||||
- Added missing sounds for using a shovel on grass to create grass path.
|
||||
- Pumpkins can now be carved using shears.
|
||||
- Brewing stands can now be used for brewing potions.
|
||||
- The visual appearance of a brewing stand now updates correctly when the contents of its inventory changes (adding/removing potions).
|
||||
- Added missing sounds for furnace, blast furnace and smoker.
|
||||
- Fixed ender chest not dropping itself when mined with a Silk Touch pickaxe.
|
||||
- Cobwebs now drop themselves when mined using shears.
|
||||
- The correct amount of fall damage is now taken when falling from a height onto hay bales.
|
||||
|
||||
### Items
|
||||
- Dropped items of the same type now merge with each other.
|
@ -1,53 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.40**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.10.0
|
||||
Released 26th October 2022.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.40.
|
||||
- Removed support for older versions.
|
||||
|
||||
## Fixes
|
||||
- Fixed incorrect command descriptions showing in `/help` when multiple commands use the same name. Previously, the most recently registered command would show, even though it wouldn't actually be invoked.
|
||||
- Fixed splash potions affecting players in spectator mode.
|
||||
- Fixed `World->addParticle()` sending particles to players who couldn't possibly see them when a list of targets was used.
|
||||
- Fixed `World->addSound()` sending sounds to players who couldn't possibly hear them when a list of targets was used.
|
||||
|
||||
## Documentation
|
||||
- Improved type information available for various API methods in `World`.
|
||||
|
||||
# 4.10.1
|
||||
Released 7th November 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed spawning in the void if spawn terrain in a world is solid at the default spawn position.
|
||||
- Fixed totems of undying activating when the player has 1 HP remaining.
|
||||
- Fixed durable items such as tools becoming unbreakable when in stacks larger than 1. Now, the durability correctly resets when the tool breaks.
|
||||
- TPS below 12 now correctly shows as red in `/status`. Previously, it showed as orange due to a condition ordering bug.
|
||||
- Improved handling of missing arguments in user-defined `pocketmine.yml` command aliases. Previously, missing arguments would be filled with an empty string, which caused a variety of unexpected behaviour.
|
||||
|
||||
## Internals
|
||||
- Added validation for the array given to `BaseInventory->setContents()` to ensure that it contains only `Item` instances.
|
||||
- Silenced `PlayerAuthInputPacket` spam when the session is in the "spawn response" state.
|
||||
- Updated to PHPStan 1.9.
|
||||
|
||||
# 4.10.2
|
||||
Released 25th November 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed crashes on macOS and Linux when using console colours without the `TERM` environment variable set.
|
||||
- Fixed crashdumps not being generated when error messages contained invalid UTF-8 characters.
|
||||
|
||||
## Documentation
|
||||
- Clarified documentation of caching behaviour for `Internet::getIP()`.
|
||||
- Added and improved documentation for many `Inventory` methods.
|
||||
- Rewritten documentation for `PlayerCreationEvent` with warnings and more detail.
|
||||
|
||||
## Internals
|
||||
- Non-arrow projectile damage is now unscaled. Scaling according to velocity is only applied to arrows. This currently doesn't cause any observable change in behaviour, but is required for future additions.
|
@ -1,92 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.40**
|
||||
|
||||
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.11.0-BETA1
|
||||
Released 7th November 2022.
|
||||
|
||||
## General
|
||||
- Packet receive timings have now been split into two subcategories - Decode and Handle.
|
||||
- Console command entry can now be disabled via the `console.enable-input` setting in `pocketmine.yml`.
|
||||
- Best suited for headless servers (e.g. in a Docker container) where the console will never be used anyway.
|
||||
- Disabling the console reader slightly reduces memory usage, because console reading currently requires an additional subprocess.
|
||||
- Console command output now appears on the terminal only, and is not written to the log file.
|
||||
- The output from console commands now appears with a `Command output |` prefix, instead of as a log message.
|
||||
- Introduced validation for the `--data` and `--plugins` command line options.
|
||||
- Encrypted resource packs are now supported, by means of adding a `.key` file alongside the pack in the `resource_packs` folder.
|
||||
- e.g. `MyEncryptedPack.zip` -> `MyEncryptedPack.zip.key`
|
||||
|
||||
## Gameplay
|
||||
- Fixed supporting blocks of dead bush to be in line with vanilla.
|
||||
- Sugarcane can now be grown using bonemeal on any part of the sugarcane. Previously, it only worked when used on the bottom block.
|
||||
- Fixed modifier values for Instant Damage and Regeneration effects.
|
||||
|
||||
## API
|
||||
### General
|
||||
- Plugins are now always disabled before their dependencies, to ensure that they are able to shutdown properly (e.g. a core plugin depending on a database plugin may want to save data to a DB during `onDisable()`).
|
||||
- [`webmozart/path-util`](https://packagist.org/packages/webmozart/path-util) has been deprecated, and will be dropped in favour of [`symfony/filesystem`](https://packagist.org/packages/symfony/filesystem) in PM5.
|
||||
- To prepare for this change, simply replace any usage of `Webmozart\PathUtil\Path` with `Symfony\Component\Filesystem\Path`, which is available as a dependency in this release.
|
||||
|
||||
### `pocketmine`
|
||||
- The following API methods are now deprecated:
|
||||
- `Server->getPlayerByPrefix()`
|
||||
|
||||
### `pocketmine\entity`
|
||||
- `EntitySpawnEvent` and `ItemSpawnEvent` are now fired on the first tick after the entity is added to the world. Previously, these events were called directly from the entity constructor, making it impossible to get properties like velocity which are often set after the entity is created.
|
||||
- The following API methods are now deprecated:
|
||||
- `Living->hasLineOfSight()`
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following new API methods have been added:
|
||||
- `public Armor->clearCustomColor() : $this`
|
||||
|
||||
### `pocketmine\inventory\transaction`
|
||||
- Introduced a `TransactionBuilder` class. This makes it less of a hassle to build an `InventoryTransaction` server-side, since the regular `Inventory` API methods can be used, rather than having to manually create `SlotChangeAction`s.
|
||||
|
||||
### `pocketmine\player`
|
||||
- The following new API methods have been added:
|
||||
- `public Player->sendToastNotification(string $title, string $body) : void` - makes a grey box appear at the top of the player's screen containing the specified message
|
||||
|
||||
### `pocketmine\utils`
|
||||
- The following new API methods have been added:
|
||||
- `public static TextFormat::addBase(string $baseFormat, string $string) : string` - used for coloured log messages, changes the base formatting of a string by inserting the given formatting codes after every RESET code
|
||||
|
||||
## Internals
|
||||
- Improved performance of `ContainerTrait` dropping items on block destroy. (24e72ec109c1442b09558df89b6833cf2f2e0ec7)
|
||||
- Avoid repeated calls to `Position->getWorld()` (use local variables). (2940547026db40ce76deb46e992870de3ead79ad)
|
||||
- Revamped the way `InventoryManager` handles fake inventory slot mappings for stuff like crafting tables. (e90abecf38d9c57635fa0497514bba7e546a2469)
|
||||
- Console polling is now done on the main thread (no longer a performance concern).
|
||||
- Console reader subprocess should now automatically die if the server main process is killed, instead of persisting as a zombie.
|
||||
- `ConsoleCommandSender` is no longer responsible for relaying broadcast messages to `MainLogger`. A new `BroadcastLoggerForwarder` has been added, which is subscribed to the appropriate server broadcast channels in order to relay messages. This ensures that chat messages and command audit messages are logged.
|
||||
- `DelegateInventory` now uses `WeakReference` to track its inventory listener. This allows the delegate to be reused.
|
||||
|
||||
# 4.11.0-BETA2
|
||||
Released 13th November 2022.
|
||||
|
||||
## Configuration
|
||||
- The `chunk-ticking.per-tick` setting is now deprecated, and will be removed in a future release.
|
||||
- The functionality of this setting has been removed, since it caused more problems than it solved.
|
||||
- Setting it to zero will still disable chunk ticking (for now), but this should now be done by setting `chunk-ticking.tick-radius` to `0` instead.
|
||||
|
||||
## Gameplay
|
||||
- Improved chunk random ticking:
|
||||
- Removed the limit on chunks ticked per tick, and its associated config option is no longer respected.
|
||||
- This change significantly improves crop and plant growth with large numbers of players, but may cause higher CPU usage.
|
||||
- This limit was causing a linear decrease in chunk ticking speed with larger numbers of players, leading to worsened gameplay experience.
|
||||
- Every chunk within the configured tick radius of a player will be ticked. Previously, chunks were randomly selected from the radius.
|
||||
- Implemented Darkness effect.
|
||||
|
||||
## API
|
||||
### `pocketmine\world`
|
||||
- The following new API methods have been added:
|
||||
- `public World->getChunkTickRadius() : int` - returns the world's simulation radius
|
||||
- `public World->setChunkTickRadius(int $radius) : void` - sets the world's simulation radius
|
||||
|
||||
## Internals
|
||||
- Non-arrow projectile damage is now unscaled. Scaling according to velocity is only applied to arrows. This currently doesn't cause any observable change in behaviour, but is required for future additions.
|
@ -1,106 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.40**
|
||||
|
||||
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.11.0
|
||||
Released 25th November 2022.
|
||||
|
||||
## General
|
||||
- Packet receive timings have now been split into two subcategories - Decode and Handle.
|
||||
- Console command entry can now be disabled via the `console.enable-input` setting in `pocketmine.yml`.
|
||||
- Best suited for headless servers (e.g. in a Docker container) where the console will never be used anyway.
|
||||
- Disabling the console reader slightly reduces memory usage, because console reading currently requires an additional subprocess.
|
||||
- Console command output now appears on the terminal only, and is not written to the log file.
|
||||
- The output from console commands now appears with a `Command output |` prefix, instead of as a log message.
|
||||
- User-defined `pocketmine.yml` custom commands now use a generic description which makes clear the command is config-defined.
|
||||
- Introduced validation for the `--data` and `--plugins` command line options.
|
||||
- Encrypted resource packs are now supported, by means of adding a `.key` file alongside the pack in the `resource_packs` folder.
|
||||
- e.g. `MyEncryptedPack.zip` -> `MyEncryptedPack.zip.key`
|
||||
- The file must contain the raw key bytes, and must not end with a newline.
|
||||
|
||||
## Configuration
|
||||
- The `chunk-ticking.per-tick` setting is now deprecated, and will be removed in a future release.
|
||||
- The functionality of this setting has been removed, since it caused more problems than it solved.
|
||||
- Setting it to zero will still disable chunk ticking (for now), but this should now be done by setting `chunk-ticking.tick-radius` to `0` instead.
|
||||
|
||||
## Gameplay
|
||||
- Fixed supporting blocks of dead bush to be in line with vanilla.
|
||||
- Sugarcane can now be grown using bonemeal on any part of the sugarcane. Previously, it only worked when used on the bottom block.
|
||||
- Fixed missing sounds when adding, rotating, or removing items in item frames.
|
||||
- Fixed modifier values for Instant Damage and Regeneration effects.
|
||||
- Implemented Darkness effect.
|
||||
- Improved chunk random ticking:
|
||||
- Removed the limit on chunks ticked per tick, and its associated config option is no longer respected.
|
||||
- This change significantly improves crop and plant growth with large numbers of players.
|
||||
- This limit was causing a linear decrease in chunk ticking speed with larger numbers of players, leading to worsened gameplay experience.
|
||||
- **Warning: This change will result in increased CPU usage if players are spread over a very large area.**
|
||||
- Every chunk within the configured tick radius of a player will be ticked. Previously, chunks were randomly selected from the radius.
|
||||
|
||||
## API
|
||||
### General
|
||||
- Plugins are now always disabled before their dependencies, to ensure that they are able to shutdown properly (e.g. a core plugin depending on a database plugin may want to save data to a DB during `onDisable()`).
|
||||
- [`webmozart/path-util`](https://packagist.org/packages/webmozart/path-util) has been deprecated, and will be dropped in favour of [`symfony/filesystem`](https://packagist.org/packages/symfony/filesystem) in PM5.
|
||||
- To prepare for this change, simply replace any usage of `Webmozart\PathUtil\Path` with `Symfony\Component\Filesystem\Path`, which is available as a dependency in this release.
|
||||
|
||||
### `pocketmine`
|
||||
- The following API methods are now deprecated:
|
||||
- `Server->getPlayerByPrefix()`
|
||||
|
||||
### `pocketmine\entity`
|
||||
- `EntitySpawnEvent` and `ItemSpawnEvent` are now fired on the first tick after the entity is added to the world. Previously, these events were called directly from the entity constructor, making it impossible to get properties like velocity which are often set after the entity is created.
|
||||
- The following API methods are now deprecated:
|
||||
- `Living->hasLineOfSight()`
|
||||
|
||||
### `pocketmine\event\block`
|
||||
- The following new classes have been added:
|
||||
- `BlockDeathEvent` - event called when coral or coral blocks die due to lack of water
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following new API methods have been added:
|
||||
- `public Armor->clearCustomColor() : $this`
|
||||
|
||||
### `pocketmine\inventory\transaction`
|
||||
- Introduced a `TransactionBuilder` class. This makes it less of a hassle to build an `InventoryTransaction` server-side, since the regular `Inventory` API methods can be used, rather than having to manually create `SlotChangeAction`s.
|
||||
|
||||
### `pocketmine\lang`
|
||||
- The following new API methods have been added:
|
||||
- `public Language->getAll() : array<string, string>`
|
||||
|
||||
### `pocketmine\player`
|
||||
- The following new API methods have been added:
|
||||
- `public Player->sendToastNotification(string $title, string $body) : void` - makes a grey box appear at the top of the player's screen containing the specified message
|
||||
|
||||
### `pocketmine\utils`
|
||||
- The following new API methods have been added:
|
||||
- `public static TextFormat::addBase(string $baseFormat, string $string) : string` - used for coloured log messages, changes the base formatting of a string by inserting the given formatting codes after every RESET code
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following new API methods have been added:
|
||||
- `public World->getChunkTickRadius() : int` - returns the world's simulation radius
|
||||
- `public World->setChunkTickRadius(int $radius) : void` - sets the world's simulation radius
|
||||
|
||||
### `pocketmine\world\sound`
|
||||
- The following new classes have been added:
|
||||
- `ItemFrameAddItemSound`
|
||||
- `ItemFrameRemoveItemSound`
|
||||
- `ItemFrameRotateItemSound`
|
||||
|
||||
## Internals
|
||||
- Improved performance of `ContainerTrait` dropping items on block destroy. ([link](https://github.com/pmmp/PocketMine-MP/commits/24e72ec109c1442b09558df89b6833cf2f2e0ec7))
|
||||
- Avoid repeated calls to `Position->getWorld()` (use local variables). ([link](https://github.com/pmmp/PocketMine-MP/commit/2940547026db40ce76deb46e992870de3ead79ad))
|
||||
- Revamped the way `InventoryManager` handles fake inventory slot mappings for stuff like crafting tables. ([link](https://github.com/pmmp/PocketMine-MP/commit/e90abecf38d9c57635fa0497514bba7e546a2469))
|
||||
- Inventories are now mapped on a per-slot basis. This means that more than one inventory can be mapped to the same window ID, which is necessary for correctly handling "UI" inventories like crafting tables.
|
||||
- `InventoryManager->getWindow(int $windowId) : ?Inventory` is replaced by `locateWindowAndSlot` (see below).
|
||||
- Added `InventoryManager->locateWindowAndSlot(int $windowId, int $netSlotId) : array{Inventory, int}` - accepts a window ID and absolute slot ID, and returns the associated inventory and the slot relative to the inventory's own start (for use with `getItem()` etc.).
|
||||
- Slot offset mapping for "UI" inventories is now handled in `InventoryManager->createComplexSlotMapping()` instead of in `TypeConverter`.
|
||||
- Console polling is now done on the main thread (no longer a performance concern). ([link](https://github.com/pmmp/PocketMine-MP/commit/b3f03d7ae645de67a54b7300c09b94eeca16298e))
|
||||
- Console reader subprocess should now automatically die if the server main process is killed, instead of persisting as a zombie. ([link](https://github.com/pmmp/PocketMine-MP/commit/2585160ca2c4df5758b8b980331307402ff9f0fb))
|
||||
- `ConsoleCommandSender` is no longer responsible for relaying broadcast messages to `MainLogger`. A new `BroadcastLoggerForwarder` has been added, which is subscribed to the appropriate server broadcast channels in order to relay messages. This ensures that chat messages and command audit messages are logged. ([link](https://github.com/pmmp/PocketMine-MP/commit/83e5b0adb6fa0dddec377182bb1c7945ac8f7820))
|
||||
- `DelegateInventory` now uses `WeakReference` to track its inventory listener. This allows the delegate to be reused. ([link](https://github.com/pmmp/PocketMine-MP/commit/3feaa18f6c10c3a99c0deca75f57ec2d74b92ab4))
|
||||
- Non-arrow projectile damage is now unscaled. Scaling according to velocity is only applied to arrows. This currently doesn't cause any observable change in behaviour, but is required for future additions.
|
@ -1,119 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.50**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.12.0
|
||||
Released 30th November 2022.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.50.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.12.1
|
||||
Released 4th December 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed items glitching when dragging a stack of items across the crafting grid (desync issues).
|
||||
|
||||
# 4.12.2
|
||||
Released 15th December 2022.
|
||||
|
||||
## Fixes
|
||||
- Folder used for plugins (optionally specified by `--plugins`) is no longer required to be writable.
|
||||
- Fixed broken writable check for server data folder (`is_writable()` broken on NFS and similar filesystems).
|
||||
- `Filesystem::createLockFile()` exceptions now include more information about why the lock file could not be created.
|
||||
- Fixed client-side item predictions not being rolled back when cancelling events such as `PlayerItemUseEvent`.
|
||||
|
||||
## Dependencies
|
||||
- Updated BedrockProtocol to [17.1.0](https://github.com/pmmp/BedrockProtocol/releases/tag/17.1.0+bedrock-1.19.50). This adds some missing `LevelSoundEvent` constants and fixes the values for `ContainerUIIds`.
|
||||
|
||||
# 4.12.3
|
||||
Released 28th December 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed unauthenticated connections taking up player count slots, preventing players from joining.
|
||||
- Fixed a possible crash in `World->tickChunk()` when plugins unload chunks during some events.
|
||||
- `/gamemode` will now report a failure to change game mode if the player is already in the requested game mode.
|
||||
|
||||
# 4.12.4
|
||||
Released 3rd January 2023.
|
||||
|
||||
## Fixes
|
||||
- Added workarounds for an active exploit being used to deny service to servers.
|
||||
|
||||
# 4.12.5
|
||||
Released 6th January 2023.
|
||||
|
||||
## Fixes
|
||||
- Removed a workaround for an old client bug in custom form responses. The code contained a denial-of-service vulnerability.
|
||||
|
||||
# 4.12.6
|
||||
Released 7th January 2023.
|
||||
|
||||
## Changes
|
||||
- Added a new security measure to `NetworkSession` to detect and ban players who flood the server with packets.
|
||||
|
||||
# 4.12.7
|
||||
Released 8th January 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed players getting kicked when the server lags for too long.
|
||||
- Fixed players getting kicked when a debugging session is active and a breakpoint is hit.
|
||||
|
||||
# 4.12.8
|
||||
Released 9th January 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed players getting kicked during PvP.
|
||||
- Fixed players randomly getting kicked on Windows (improper rate limit handling wrt. 15ms timer resolution).
|
||||
|
||||
# 4.12.9
|
||||
Released 16th January 2023.
|
||||
|
||||
## Improvements
|
||||
### Timings
|
||||
- Added new timers:
|
||||
- `Server Mid-Tick Processing` - time spent processing Snooze interrupts between ticks (e.g. incoming network packets)
|
||||
- `Server Tick Update Cycle` - time spent processing regular per-tick updates (e.g. entity movement, world updates, etc.) (`Server->tick()`)
|
||||
- `Full Server Tick` timer now counts the total of `Server Mid-Tick Processing` and `Server Tick Update Cycle`, which generates more accurate performance metrics.
|
||||
- Previously, this timer only counted the time spent during regular per-tick updates, and the time recorded by `Server Mid-Tick Processing` was not included in the report at all.
|
||||
|
||||
## Fixes
|
||||
- Fixed blocks such as pressure plates being able to be placed without the correct supporting blocks if the clicked block was solid.
|
||||
- Pressure plates now self-destruct when the block below them is removed.
|
||||
- Fixed being unable to place blocks by clicking on the side of a bell (when the click doesn't result in ringing the bell).
|
||||
- Fixed various rotation-aware blocks (e.g. stairs) behaving incorrectly when placed by clicking on the side of a replaceable block (e.g. tall grass).
|
||||
- Fixed banners being able to be placed on top of blocks such as skulls.
|
||||
- Fixed server-side collision boxes of walls and glass (which should connect, but didn't). Note that wall connections still don't show client side - this just fixes the collision boxes.
|
||||
- Fixed `PlayerInteractEvent` with `LEFT_CLICK` sometimes firing before `BlockBreakEvent` when breaking blocks.
|
||||
|
||||
## Other changes
|
||||
- Increased packet batch budget for player sessions.
|
||||
|
||||
# 4.12.10
|
||||
Released 18th January 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed reported server load not including the time spent processing Snooze interrupts between ticks (e.g. incoming network packets).
|
||||
- Fixed `Connection Handler` entry in timings report not including time spent receiving packets.
|
||||
|
||||
## Note about server load & performance
|
||||
This version will report higher apparent server load than previous versions. The actual performance of the server is unchanged; the previous reported load was inaccurate.
|
||||
These bugs have been present for nearly 5 years (ever since the first introduction of Snooze in 3.0.0).
|
||||
|
||||
# 4.12.11
|
||||
Released 22nd January 2023.
|
||||
|
||||
## General
|
||||
- Code is now tested and analysed using PHP 8.2 in addition to 8.1 and 8.0.
|
||||
|
||||
## Fixes
|
||||
- Fixed pthreads 5.0.0 incorrectly being treated as compatible.
|
||||
- Fixed deprecation errors on PHP 8.2.
|
||||
|
||||
## Documentation
|
||||
- Updated documentation in `PlayerPreLoginEvent`.
|
@ -1,94 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.50**
|
||||
|
||||
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.13.0-BETA1
|
||||
Released 18th January 2023.
|
||||
|
||||
## Gameplay
|
||||
- Death message is now shown on the death screen when a player dies.
|
||||
- Armour damage is now only increased if the armour reduced the damage taken.
|
||||
- Implemented Swift Sneak enchantment.
|
||||
- Fixed incorrect collision box calculation of walls and glass/bars when connected. Note: Client-side, wall connections are still broken; this only fixes projectile flight server-side.
|
||||
|
||||
## Performance
|
||||
- Improved performance of chunk selection for chunk random ticking using a cache. This improves performance of chunk random ticking by 10-20%.
|
||||
|
||||
## Localization
|
||||
- Added localized description for the `/dumpmemory` command.
|
||||
|
||||
## Permissions
|
||||
- Added the following new core permissions:
|
||||
- `pocketmine.command.effect.other` - allows the player to use the `/effect` command on other players (default operator only)
|
||||
- `pocketmine.command.effect.self` - allows the player to use the `/effect` command on themselves (default operator only)
|
||||
- `pocketmine.command.enchant.other` - allows the player to use the `/enchant` command on other players (default operator only)
|
||||
- `pocketmine.command.enchant.self` - allows the player to use the `/enchant` command on themselves (default operator only)
|
||||
- `pocketmine.command.gamemode.other` - allows the player to use the `/gamemode` command on other players (default operator only)
|
||||
- `pocketmine.command.gamemode.self` - allows the player to use the `/gamemode` command on themselves (default operator only)
|
||||
- `pocketmine.command.give.other` - allows the player to use the `/give` command on other players (default operator only)
|
||||
- `pocketmine.command.give.self` - allows the player to use the `/give` command on themselves (default operator only)
|
||||
- `pocketmine.command.spawnpoint.other` - allows the player to use the `/spawnpoint` command on other players (default operator only)
|
||||
- `pocketmine.command.spawnpoint.self` - allows the player to use the `/spawnpoint` command on themselves (default operator only)
|
||||
- `pocketmine.command.teleport.other` - allows the player to use the `/teleport` command on other players (default operator only)
|
||||
- `pocketmine.command.teleport.self` - allows the player to use the `/teleport` command on themselves (default operator only)
|
||||
- `pocketmine.command.title.other` - allows the player to use the `/title` command on other players (default operator only)
|
||||
- `pocketmine.command.title.self` - allows the player to use the `/title` command on themselves (default operator only)
|
||||
|
||||
## Internals
|
||||
- Decoupled `Player->sendMessage()` and `Player->sendTranslation()`.
|
||||
- Refactored resource pack loading in `ResourcePackManager` to make it easier to understand.
|
||||
- Client-aware translation processing has been moved to `NetworkSession` due to being client-specific.
|
||||
- Replaced hardcoded strings with constants in various places.
|
||||
- `NetworkSession` destructive cleanup is now deferred to the next session tick. This fixes various `InventoryManager` crashes when kicking players during events.
|
||||
- Updated code using `strpos()` to use `str_starts_with()`, `str_ends_with()` and `str_contains()` where appropriate.
|
||||
- Added documentation for some internal methods.
|
||||
|
||||
## API
|
||||
### `pocketmine\command`
|
||||
- The following new API methods have been added:
|
||||
- `protected VanillaCommand->fetchPermittedPlayerTarget(...) : ?Player` - fetches a player target according to the given sender permissions, or null if not found or not permitted
|
||||
|
||||
### `pocketmine\entity`
|
||||
- The following new API methods have been added:
|
||||
- `public Living->getDisplayName() : string` - the name of the entity to be shown in death messages, commands etc.
|
||||
|
||||
### `pocketmine\event\world`
|
||||
- The following new classes have been added:
|
||||
- `WorldSoundEvent` - called when a sound is played in a world
|
||||
- `WorldParticleEvent` - called when a particle is spawned in a world
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following new API methods have been added:
|
||||
- `public Item->onInteractEntity(Player $player, Entity $entity, Vector3 $clickVector) : bool` - called when a player interacts with an entity with this item in hand
|
||||
|
||||
### `pocketmine\lang`
|
||||
- `Language->translate()` and `Language->translateString()` no longer parse nested translation in the "base text". This was never intended behaviour, and didn't work beyond the first level anyway.
|
||||
|
||||
### `pocketmine\player`
|
||||
- The following new interfaces have been added:
|
||||
- `PlayerDataProvider` - implemented by classes which want to offer storage for player data
|
||||
- The following new classes have been added:
|
||||
- `DatFilePlayerDataProvider` - the default player data provider, which stores `.dat` files in the `players` folder
|
||||
- `PlayerDataLoadException` - thrown when an error occurs while loading player data
|
||||
- `PlayerDataSaveException` - thrown when an error occurs while saving player data
|
||||
- The following API methods have been deprecated:
|
||||
- `Player->sendTranslation()` - use `Player->sendMessage()` instead with a `Translatable` message
|
||||
|
||||
### `pocketmine\resourcepacks`
|
||||
- The following new API methods have been added:
|
||||
- `public ResourcePackManager->setResourceStack(list<ResourcePack> $resourceStack) : void` - sets the list of resource packs to be applied by players
|
||||
- `public ResourcePackManager->setPackEncryptionKey(string $id, ?string $key) : void` - sets the encryption key to be used for a resource pack
|
||||
|
||||
### `pocketmine\utils`
|
||||
- The following new API methods have been added:
|
||||
- `public static Filesystem::fileGetContents(...) : string` - a wrapper around `file_get_contents()` which throws an exception on failure
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following new API methods have been added:
|
||||
- `public World->requestSafeSpawn(?Vector3 $spawn = null) : Promise<Position>` - an async version of `getSafeSpawn()` which generates all the needed chunks before returning
|
@ -1,94 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.50**
|
||||
|
||||
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.13.0
|
||||
Released 30th January 2023.
|
||||
|
||||
## Gameplay
|
||||
- Death message is now shown on the death screen when a player dies.
|
||||
- Armour damage is now only increased if the armour reduced the damage taken.
|
||||
- Implemented Swift Sneak enchantment.
|
||||
- Fixed incorrect collision box calculation of walls and glass/bars when connected. Note: Client-side, wall connections are still broken; this only fixes projectile flight server-side.
|
||||
|
||||
## Performance
|
||||
- Improved performance of chunk selection for chunk random ticking using a cache. This improves performance of chunk random ticking by 10-20%.
|
||||
|
||||
## Localization
|
||||
- Added localized description for the `/dumpmemory` command.
|
||||
|
||||
## Permissions
|
||||
- Added the following new core permissions:
|
||||
- `pocketmine.command.effect.other` - allows the player to use the `/effect` command on other players (default operator only)
|
||||
- `pocketmine.command.effect.self` - allows the player to use the `/effect` command on themselves (default operator only)
|
||||
- `pocketmine.command.enchant.other` - allows the player to use the `/enchant` command on other players (default operator only)
|
||||
- `pocketmine.command.enchant.self` - allows the player to use the `/enchant` command on themselves (default operator only)
|
||||
- `pocketmine.command.gamemode.other` - allows the player to use the `/gamemode` command on other players (default operator only)
|
||||
- `pocketmine.command.gamemode.self` - allows the player to use the `/gamemode` command on themselves (default operator only)
|
||||
- `pocketmine.command.give.other` - allows the player to use the `/give` command on other players (default operator only)
|
||||
- `pocketmine.command.give.self` - allows the player to use the `/give` command on themselves (default operator only)
|
||||
- `pocketmine.command.spawnpoint.other` - allows the player to use the `/spawnpoint` command on other players (default operator only)
|
||||
- `pocketmine.command.spawnpoint.self` - allows the player to use the `/spawnpoint` command on themselves (default operator only)
|
||||
- `pocketmine.command.teleport.other` - allows the player to use the `/teleport` command on other players (default operator only)
|
||||
- `pocketmine.command.teleport.self` - allows the player to use the `/teleport` command on themselves (default operator only)
|
||||
- `pocketmine.command.title.other` - allows the player to use the `/title` command on other players (default operator only)
|
||||
- `pocketmine.command.title.self` - allows the player to use the `/title` command on themselves (default operator only)
|
||||
|
||||
## Internals
|
||||
- Decoupled `Player->sendMessage()` and `Player->sendTranslation()`.
|
||||
- Refactored resource pack loading in `ResourcePackManager` to make it easier to understand.
|
||||
- Client-aware translation processing has been moved to `NetworkSession` due to being client-specific.
|
||||
- Replaced hardcoded strings with constants in various places.
|
||||
- `NetworkSession` destructive cleanup is now deferred to the next session tick. This fixes various `InventoryManager` crashes when kicking players during events.
|
||||
- Updated code using `strpos()` to use `str_starts_with()`, `str_ends_with()` and `str_contains()` where appropriate.
|
||||
- Added documentation for some internal methods.
|
||||
|
||||
## API
|
||||
### `pocketmine\command`
|
||||
- The following new API methods have been added:
|
||||
- `protected VanillaCommand->fetchPermittedPlayerTarget(...) : ?Player` - fetches a player target according to the given sender permissions, or null if not found or not permitted
|
||||
|
||||
### `pocketmine\entity`
|
||||
- The following new API methods have been added:
|
||||
- `public Living->getDisplayName() : string` - the name of the entity to be shown in death messages, commands etc.
|
||||
|
||||
### `pocketmine\event\world`
|
||||
- The following new classes have been added:
|
||||
- `WorldSoundEvent` - called when a sound is played in a world
|
||||
- `WorldParticleEvent` - called when a particle is spawned in a world
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following new API methods have been added:
|
||||
- `public Item->onInteractEntity(Player $player, Entity $entity, Vector3 $clickVector) : bool` - called when a player interacts with an entity with this item in hand
|
||||
|
||||
### `pocketmine\lang`
|
||||
- `Language->translate()` and `Language->translateString()` no longer parse nested translation in the "base text". This was never intended behaviour, and didn't work beyond the first level anyway.
|
||||
|
||||
### `pocketmine\player`
|
||||
- The following new interfaces have been added:
|
||||
- `PlayerDataProvider` - implemented by classes which want to offer storage for player data
|
||||
- The following new classes have been added:
|
||||
- `DatFilePlayerDataProvider` - the default player data provider, which stores `.dat` files in the `players` folder
|
||||
- `PlayerDataLoadException` - thrown when an error occurs while loading player data
|
||||
- `PlayerDataSaveException` - thrown when an error occurs while saving player data
|
||||
- The following API methods have been deprecated:
|
||||
- `Player->sendTranslation()` - use `Player->sendMessage()` instead with a `Translatable` message
|
||||
|
||||
### `pocketmine\resourcepacks`
|
||||
- The following new API methods have been added:
|
||||
- `public ResourcePackManager->setResourceStack(list<ResourcePack> $resourceStack) : void` - sets the list of resource packs to be applied by players
|
||||
- `public ResourcePackManager->setPackEncryptionKey(string $id, ?string $key) : void` - sets the encryption key to be used for a resource pack
|
||||
|
||||
### `pocketmine\utils`
|
||||
- The following new API methods have been added:
|
||||
- `public static Filesystem::fileGetContents(...) : string` - a wrapper around `file_get_contents()` which throws an exception on failure
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following new API methods have been added:
|
||||
- `public World->requestSafeSpawn(?Vector3 $spawn = null) : Promise<Position>` - an async version of `getSafeSpawn()` which generates all the needed chunks before returning
|
@ -1,21 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.60**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.14.0
|
||||
Released 8th February 2023.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.60.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.14.1
|
||||
Released 15th February 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed all players getting kicked with `Receiving packets too fast` if a server tick takes longer than 5 seconds (e.g. because of autosave or GC).
|
||||
- Fixed players getting kicked when linking with entities.
|
@ -1,38 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.62**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.15.0
|
||||
Released 17th February 2023.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.62.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.15.1
|
||||
Released 21st February 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed dropped items not despawning when in non-ticking chunks.
|
||||
- Fixed dropped items not despawning if an infinite pickup delay is set.
|
||||
- Fixed infinite despawn delay (never despawn) being ignored for dropped items.
|
||||
|
||||
# 4.15.2
|
||||
Released 24th February 2023.
|
||||
|
||||
## General
|
||||
- Accept Minecraft: Bedrock Edition 1.19.63 (identical protocol to 1.19.62, but different version due to Mojang mixup).
|
||||
|
||||
## Fixes
|
||||
- Fixed `World Population` timer sometimes not being stopped, causing strange results in timings reports.
|
||||
|
||||
# 4.15.3
|
||||
Released 7th March 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed `/dumpmemory` crash when any object contained an `INF` or `NaN` float value.
|
||||
- Updated RakLib for security fixes.
|
@ -1,45 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.62**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.16.0-BETA1
|
||||
Released 4th March 2023.
|
||||
|
||||
## General
|
||||
- Added granular timings for packet encode, similar to the existing timings for packet decode.
|
||||
- Timings now covers several areas of the network system which were previously not counted by network timings, but were counted by total timings. This provides a better insight into the performance of the network system.
|
||||
|
||||
## Performance
|
||||
- Improved performance of packet batch handling by avoiding unnecessary object allocations.
|
||||
- Improved performance of packet broadcasting when the broadcast size is below the batch threshold. Previously, the packets would be encoded once by every recipient, but now they are encoded once and then added to the send buffer of each session in their raw form.
|
||||
- This change mostly affects servers with larger maps, where players are more widely distributed.
|
||||
|
||||
## Build system
|
||||
- Added a new script `build/generate-bedrockdata-path-consts.php`, which must be run whenever BedrockData is updated. This script generates a class of constants with the file paths of all BedrockData files.
|
||||
|
||||
## API
|
||||
### `pocketmine\entity`
|
||||
- The following new API methods have been added:
|
||||
- `public Entity->getGravity() : float` - returns the entity's gravity acceleration in blocks/tick^2
|
||||
- `public Entity->setGravity(float $gravity) : void` - sets the entity's gravity acceleration in blocks/tick^2
|
||||
|
||||
## Internals
|
||||
- Now uses [`pocketmine/bedrock-data` 2.0.0](https://github.com/pmmp/BedrockData/releases/tag/2.0.0+bedrock-1.19.60).
|
||||
- This version is now used by both PM4 and PM5, reducing maintenance burden.
|
||||
- Now uses [`pocketmine/bedrock-protocol` 19.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/19.3.0+bedrock-1.19.62).
|
||||
- This version provides new APIs for handling packet batches which enabled improving performance and adding new features, such as detailed packet encode timings.
|
||||
- Crafting recipes and creative inventory data are now loaded from `recipes/legacy_recipes.json` and `recipes/legacy_creativeitems.json` respectively. Previously, these were loaded from BedrockData directly, but BedrockData 2.0 now uses a format which can't be supported in 4.x without BC breaks.
|
||||
- Added dependencies on [`pocketmine/bedrock-block-upgrade-schema`](https://github.com/pmmp/BedrockBlockUpgradeSchema) and [`pocketmine/bedrock-item-upgrade-schema`](https://github.com/pmmp/BedrockItemUpgradeSchema). These provide mapping files no longer present in BedrockData 2.0.
|
||||
- Reduced and/or eliminated most usages of `PacketBatch`, since it only appeared as a throwaway object and was therefore wasting performance.
|
||||
- `Compressor` now exposes `getCompressionThreshold()` instead of `willCompress()`, which allows determining whether a batch will be compressed without allocating it.
|
||||
- Added `pocketmine\data\bedrock\BedrockDataFiles`, an auto-generated class of constants with the file paths of all BedrockData files. This makes it easier to locate usages, detect unused files and avoid typos.
|
||||
|
||||
# 4.16.0-BETA2
|
||||
Released 4th March 2023.
|
||||
|
||||
## General
|
||||
- Fixed incorrect release channel for 4.16.0-BETA1.
|
@ -1,41 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.62**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.16.0
|
||||
Released 7th March 2023.
|
||||
|
||||
## General
|
||||
- Added granular timings for packet encode, similar to the existing timings for packet decode.
|
||||
- Split `Player Network Send - Compression` timings into two timers, one for `Session Buffer` compression and one for `Broadcast` compression.
|
||||
- Timings now covers several areas of the network system which were previously not counted by network timings, but were counted by total timings. This provides a better insight into the performance of the network system.
|
||||
|
||||
## Performance
|
||||
- Improved performance of packet batch handling by avoiding unnecessary object allocations.
|
||||
- Improved performance of packet broadcasting when the broadcast size is below the batch threshold. Previously, the packets would be encoded once by every recipient, but now they are encoded once and then added to the send buffer of each session in their raw form.
|
||||
- This change mostly affects servers with larger maps, where players are more widely distributed.
|
||||
- Improved performance of packet broadcasting when the broadcast has only one recipient (allow the session to compress the packet with the rest of its buffer).
|
||||
|
||||
## Build system
|
||||
- Added a new script `build/generate-bedrockdata-path-consts.php`, which must be run whenever BedrockData is updated. This script generates a class of constants with the file paths of all BedrockData files.
|
||||
|
||||
## API
|
||||
### `pocketmine\entity`
|
||||
- The following new API methods have been added:
|
||||
- `public Entity->getGravity() : float` - returns the entity's gravity acceleration in blocks/tick^2
|
||||
- `public Entity->setGravity(float $gravity) : void` - sets the entity's gravity acceleration in blocks/tick^2
|
||||
|
||||
## Internals
|
||||
- Now uses [`pocketmine/bedrock-data` 2.0.0](https://github.com/pmmp/BedrockData/releases/tag/2.0.0+bedrock-1.19.60).
|
||||
- This version is now used by both PM4 and PM5, reducing maintenance burden.
|
||||
- Now uses [`pocketmine/bedrock-protocol` 19.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/19.3.0+bedrock-1.19.62).
|
||||
- This version provides new APIs for handling packet batches which enabled improving performance and adding new features, such as detailed packet encode timings.
|
||||
- Crafting recipes and creative inventory data are now loaded from `recipes/legacy_recipes.json` and `recipes/legacy_creativeitems.json` respectively. Previously, these were loaded from BedrockData directly, but BedrockData 2.0 now uses a format which can't be supported in 4.x without BC breaks.
|
||||
- Added dependencies on [`pocketmine/bedrock-block-upgrade-schema`](https://github.com/pmmp/BedrockBlockUpgradeSchema) and [`pocketmine/bedrock-item-upgrade-schema`](https://github.com/pmmp/BedrockItemUpgradeSchema). These provide mapping files no longer present in BedrockData 2.0.
|
||||
- Reduced and/or eliminated most usages of `PacketBatch`, since it only appeared as a throwaway object and was therefore wasting performance.
|
||||
- `Compressor` now exposes `getCompressionThreshold()` instead of `willCompress()`, which allows determining whether a batch will be compressed without allocating it.
|
||||
- Added `pocketmine\data\bedrock\BedrockDataFiles`, an auto-generated class of constants with the file paths of all BedrockData files. This makes it easier to locate usages, detect unused files and avoid typos.
|
@ -1,39 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.70**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.17.0
|
||||
Released 14th March 2023.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.70.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.17.1
|
||||
Released 22nd March 2023.
|
||||
|
||||
## General
|
||||
- Docker images for PocketMine-MP are now published on [GitHub Container Registry](https://github.com/pmmp/PocketMine-MP/pkgs/container/pocketmine-mp). The Docker Hub images will stop being maintained in the future.
|
||||
- Updated translations.
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash on empty packets in certain cases.
|
||||
- Fixed mushroom blocks dropping the wrong items when broken with a silk-touch tool.
|
||||
- Fixed mushroom blocks giving the wrong items when block-picked.
|
||||
- Fixed missing ability flag `PRIVILEGED_BUILDER`.
|
||||
|
||||
## Internals
|
||||
- `update-updater-api.yml` workflow now uses `github.repository_owner` to make it easier to test the workflow on forks.
|
||||
- Added version-specific channels to `update.pmmp.io`, such as `4`, `4.18-beta`, `4.17`, etc.
|
||||
- Replaced deprecated `::set-output` commands in GitHub Actions workflows.
|
||||
- `build/make-release.php` no longer automatically pushes changes, to avoid accidents when testing release workflows on forks.
|
||||
|
||||
# 4.17.2
|
||||
Released 29th March 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed players being unable to join due to the appearance of a new `x5t` field in the JWT header of Xbox Live authentication tokens.
|
@ -1,91 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.70**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the `pocketmine\network\mcpe` namespace are compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
### Alpha release warning
|
||||
Alpha releases are **experimental**. Features introduced in these releases are subject to change or removal.
|
||||
|
||||
APIs which existed **prior** to this version will continue to work as normal, so plugins which use them will continue to work.
|
||||
|
||||
### Highlights
|
||||
This version makes changes to the internal network system to improve server performance and reduce memory usage.
|
||||
|
||||
While these changes don't affect non-internal API, they are still significant enough to warrant a new minor version, as they may break plugins which use the internal network API (not recommended).
|
||||
|
||||
# 4.18.0-ALPHA1
|
||||
Released 16th March 2023.
|
||||
|
||||
## General
|
||||
- Improved server performance in congested areas of the world (lots of players and/or entities in the same area).
|
||||
|
||||
## API
|
||||
### `pocketmine\event\server`
|
||||
- The following new classes have been added:
|
||||
- `DataPacketDecodeEvent` - called before a packet is decoded by a `NetworkSession`; useful to mitigate DoS attacks if PocketMine-MP hasn't been patched against new bugs yet
|
||||
|
||||
## Internals
|
||||
- Introduced new system for broadcasting entity events to network sessions.
|
||||
- This change improves performance when lots of players and/or entities are in the same area.
|
||||
- New interface `EntityEventBroadcaster` and class `StandardEntityEventBroadcaster` have been added to implement this.
|
||||
- All entity-specific `on*()` and `sync*()` methods have been removed from `NetworkSession` (BC break).
|
||||
- `NetworkSession` now accepts an `EntityEventBroadcaster` instance in its constructor.
|
||||
- `NetworkBroadcastUtils::broadcastEntityEvent()` can be used to efficiently broadcast events to unique broadcasters shared by several network sessions.
|
||||
- All network sessions now share the same `PacketSerializerContext` and `PacketBroadcaster` by default.
|
||||
- Previously, every session had its own context, meaning that broadcast optimisations were not used, causing significant performance losses compared to 3.x.
|
||||
- This change improves performance in congested areas by allowing reuse of previously encoded packet buffers for all sessions sharing the same context.
|
||||
- Packet broadcasts are automatically encoded separately per unique `PacketSerializerContext` instance. This allows, for example, a multi-version fork to have a separate context for each protocol version, to ensure maximum broadcast efficiency while encoding different packets for different versions.
|
||||
- `PacketSerializerContext` is now passed in `NetworkSession::__construct()`, instead of being created by the session.
|
||||
- `StandardPacketBroadcaster` is now locked to a single `PacketSerializer` context, reducing complexity.
|
||||
- Introduced `NetworkBroadcastUtils::broadcastPackets()`, replacing `Server->broadcastPackets()`.
|
||||
- `Server->broadcastPackets()` has been deprecated. It will be removed in a future version.
|
||||
|
||||
# 4.18.0-ALPHA2
|
||||
Released 21st March 2023.
|
||||
|
||||
## General
|
||||
- Included more sections of the network system in Player Network Send timings.
|
||||
- Changed the names of some timings to make them more user-friendly.
|
||||
- Removed packet IDs from `receivePacket` and `sendPacket` timings, as they were not very useful.
|
||||
- Added new specialized timers for the following:
|
||||
- Item entity base ticking (merging)
|
||||
- Player movement processing
|
||||
- Entity movement processing (collision checking section)
|
||||
- Projectile movement (all)
|
||||
- Projectile movement processing (ray tracing section)
|
||||
|
||||
## API
|
||||
### `pocketmine\crafting`
|
||||
- The following new API methods have been added:
|
||||
- `CraftingManager->getCraftingRecipeIndex() : array<int, CraftingRecipe>` - returns a list of all crafting recipes
|
||||
- `CraftingManager->getCraftingRecipeFromIndex(int $index) : ?CraftingRecipe` - returns the crafting recipe at the given index, or null if it doesn't exist
|
||||
|
||||
### `pocketmine\inventory\transaction`
|
||||
- The following API methods have changed signatures:
|
||||
- `CraftingTransaction->__construct()` now accepts additional arguments `?CraftingRecipe $recipe = null, ?int $repetitions = null`
|
||||
- The following new API methods have been added:
|
||||
- `TransactionBuilderInventory->getActualInventory() : Inventory` - returns the actual inventory that this inventory is a proxy for
|
||||
|
||||
## Internals
|
||||
### Network
|
||||
- Introduced support for the `ItemStackRequest` Minecraft: Bedrock network protocol.
|
||||
- This fixes a large number of inventory- and crafting-related bugs.
|
||||
- This also improves server security by closing off many code pathways that might have been used for exploits. `TypeConverter->netItemStackToCore()` is no longer used in server code, and remains for tool usage only.
|
||||
- This system is also significantly more bandwidth-efficient and has lower overhead than the legacy system.
|
||||
- This now opens the gateway to easily implement lots of gameplay features which have been missing for a long time, such as enchanting, anvils, looms, and more.
|
||||
- Significant changes have been made to `pocketmine\network\mcpe\InventoryManager` internals. These shouldn't affect plugins, but may affect plugins which use internal network API.
|
||||
- **No changes have been made to the plugin `InventoryTransaction` API**.
|
||||
- This system has been implemented as a shim for the existing PocketMine-MP transaction system to preserve plugin compatibility. Plugins using `InventoryTransactionEvent` should continue to work seamlessly.
|
||||
- The `InventoryTransaction` API will be redesigned in a future major version to make use of the new information provided by the `ItemStackRequest` system.
|
||||
- `InventoryTransactionPacket` is no longer sent by the client for "regular" inventory actions. However, it is still sent when dropping items, interacting with blocks, and using items.
|
||||
- Inventory slot and content syncing is now buffered until the end of the tick. This reduces outbound network usage when the client performs multiple transactions in a single tick (e.g. crafting a stack of items).
|
||||
- Renamed some `InventoryManager` internal properties to make them easier to understand.
|
||||
- `TypeConverter->createInventoryAction()` has been removed.
|
||||
- Packet batch limit has been lowered to `100` packets. With the introduction of `ItemStackRequest`, this is more than sufficient for normal gameplay.
|
||||
|
||||
### Other
|
||||
- Use `Vector3::zero()` instead of `new Vector3()` in some places.
|
@ -1,123 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.70**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the `pocketmine\network\mcpe` namespace are compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
### Highlights
|
||||
This version significantly improves server performance with many players and/or entities by making changes to the internal network system.
|
||||
|
||||
It also introduces support for the newer `ItemStackRequest` protocol, which fixes many bugs and improves server security.
|
||||
|
||||
While these changes don't affect non-internal API, they are still significant enough to warrant a new minor version, as they may break plugins which use the internal network API (not recommended).
|
||||
|
||||
# 4.18.0
|
||||
Released 25th March 2023.
|
||||
|
||||
## General
|
||||
- Significantly improved server performance in congested areas of the world (lots of players and/or entities in the same area).
|
||||
- Included more sections of the network system in `Player Network Send` performance timings.
|
||||
- Changed the names of some performance timings to make them more user-friendly.
|
||||
- Removed packet IDs from `receivePacket` and `sendPacket` performance timings, as they were not very useful.
|
||||
- Added new specialized performance timings for the following:
|
||||
- Item entity base ticking (merging)
|
||||
- Player movement processing
|
||||
- Entity movement processing (collision checking section)
|
||||
- Projectile movement (all)
|
||||
- Projectile movement processing (ray tracing section)
|
||||
|
||||
## API
|
||||
### `pocketmine\crafting`
|
||||
- The following new API methods have been added:
|
||||
- `CraftingManager->getCraftingRecipeIndex() : array<int, CraftingRecipe>` - returns a list of all crafting recipes
|
||||
- `CraftingManager->getCraftingRecipeFromIndex(int $index) : ?CraftingRecipe` - returns the crafting recipe at the given index, or null if it doesn't exist
|
||||
|
||||
### `pocketmine\event\server`
|
||||
- The following new classes have been added:
|
||||
- `DataPacketDecodeEvent` - called before a packet is decoded by a `NetworkSession`; useful to mitigate DoS attacks if PocketMine-MP hasn't been patched against new bugs yet
|
||||
|
||||
### `pocketmine\inventory\transaction`
|
||||
- The following API methods have changed signatures:
|
||||
- `CraftingTransaction->__construct()` now accepts additional arguments `?CraftingRecipe $recipe = null, ?int $repetitions = null`
|
||||
- The following new API methods have been added:
|
||||
- `TransactionBuilderInventory->getActualInventory() : Inventory` - returns the actual inventory that this inventory is a proxy for
|
||||
|
||||
## Internals
|
||||
### Network
|
||||
- Introduced new system for broadcasting entity events to network sessions.
|
||||
- This change improves performance when lots of players and/or entities are in the same area.
|
||||
- New interface `EntityEventBroadcaster` and class `StandardEntityEventBroadcaster` have been added to implement this.
|
||||
- All entity-specific `on*()` and `sync*()` methods have been removed from `NetworkSession` (internals backwards compatibility break, not covered by API version guarantee).
|
||||
- `NetworkSession` now accepts an `EntityEventBroadcaster` instance in its constructor.
|
||||
- `NetworkBroadcastUtils::broadcastEntityEvent()` can be used to efficiently broadcast events to unique broadcasters shared by several network sessions.
|
||||
- All network sessions now share the same `PacketSerializerContext` and `PacketBroadcaster` by default.
|
||||
- Previously, every session had its own context, meaning that broadcast optimisations were not used, causing significant performance losses compared to 3.x.
|
||||
- This change improves performance in congested areas by allowing reuse of previously encoded packet buffers for all sessions sharing the same context.
|
||||
- Packet broadcasts are automatically encoded separately per unique `PacketSerializerContext` instance. This allows, for example, a multi-version fork to have a separate context for each protocol version, to ensure maximum broadcast efficiency while encoding different packets for different versions.
|
||||
- `PacketSerializerContext` is now passed in `NetworkSession::__construct()`, instead of being created by the session.
|
||||
- `StandardPacketBroadcaster` is now locked to a single `PacketSerializer` context, reducing complexity.
|
||||
- Introduced `NetworkBroadcastUtils::broadcastPackets()`, replacing `Server->broadcastPackets()`.
|
||||
- `Server->broadcastPackets()` has been deprecated. It will be removed in a future version.
|
||||
- Introduced support for the `ItemStackRequest` Minecraft: Bedrock network protocol.
|
||||
- This fixes a large number of inventory- and crafting-related bugs.
|
||||
- This also improves server security by closing off many code pathways that might have been used for exploits. `TypeConverter->netItemStackToCore()` is no longer used in server code, and remains for tool usage only.
|
||||
- This system is also significantly more bandwidth-efficient and has lower overhead than the legacy system.
|
||||
- This now opens the gateway to easily implement lots of gameplay features which have been missing for a long time, such as enchanting, anvils, looms, and more.
|
||||
- Significant changes have been made to `pocketmine\network\mcpe\InventoryManager` internals. These shouldn't affect plugins, but may affect plugins which use internal network API.
|
||||
- **No changes have been made to the plugin `InventoryTransaction` API**.
|
||||
- This system has been implemented as a shim for the existing PocketMine-MP transaction system to preserve plugin compatibility. Plugins using `InventoryTransactionEvent` should continue to work seamlessly.
|
||||
- The `InventoryTransaction` API will be redesigned in a future major version to make use of the new information provided by the `ItemStackRequest` system.
|
||||
- `InventoryTransactionPacket` is no longer sent by the client for "regular" inventory actions. However, it is still sent when dropping items, interacting with blocks, and using items.
|
||||
- Inventory slot and content syncing is now buffered until the end of the tick. This reduces outbound network usage when the client performs multiple transactions in a single tick (e.g. crafting a stack of items).
|
||||
- Renamed some `InventoryManager` internal properties to make them easier to understand.
|
||||
- `TypeConverter->createInventoryAction()` has been removed.
|
||||
- Packet batch limit has been lowered to `100` packets. With the introduction of `ItemStackRequest`, this is more than sufficient for normal gameplay.
|
||||
|
||||
### Other
|
||||
- Use `Vector3::zero()` instead of `new Vector3()` in some places.
|
||||
|
||||
# 4.18.1
|
||||
Released 27th March 2023.
|
||||
|
||||
## General
|
||||
- `RakLibInterface` now logs the name of the currently active session if a crash occurs when processing a packet. This makes it easier to reproduce bugs, which is important to be able to fix them.
|
||||
- Added more detailed debugging information to `InventoryManager->syncSelectedHotbarSlot()`.
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash when attempting to drop more of an item from a stack than available in the inventory.
|
||||
- Fixed packet processing errors when editing writable books.
|
||||
- Fixed packet processing errors when shift-clicking on the recipe book to craft recipes which draw from a large number of inventory slots.
|
||||
|
||||
# 4.18.2
|
||||
Released 29th March 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed players being unable to join due to the appearance of a new `x5t` field in the JWT header of Xbox Live authentication tokens.
|
||||
- Fixed items' durability appearing to reset when moving them around in the inventory.
|
||||
|
||||
# 4.18.3
|
||||
Released 5th April 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed Average Players not being shown on timings reports when custom player classes are used.
|
||||
- Fixed incorrect tick violation calculation in timings reports.
|
||||
- Fixed not being able to add or remove items from the offhand slot.
|
||||
- Fixed creative inventory item count corruption when taking items (some players would see 64x items in the creative inventory after rejoining or changing gamemode).
|
||||
- Fixed not being able to drop items directly from the creative inventory on mobile.
|
||||
- Fixed `DataPacketReceiveEvent` not being called for packets sent by `EntityEventBroadcaster`.
|
||||
- `CreativeInventory::getItem()` and `CreativeInventory::getAll()` now return cloned itemstacks, to prevent accidental modification of the creative inventory.
|
||||
|
||||
# 4.18.4
|
||||
Released 10th April 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed movement becoming broken when the player moves at high speed (e.g. due to high levels of the Speed effect).
|
||||
- Updated dependencies to get fixes in `pocketmine/nbt` and `pocketmine/bedrock-protocol`.
|
||||
|
||||
## Internals
|
||||
### Network
|
||||
- Game packets are now rate-limited in a similar manner to packet batches. This helps to more effectively mitigate certain types of DoS attacks.
|
||||
- Added a new class `PacketRateLimiter`, implementing functionality previously baked directly into `NetworkSession` in a more generic way to allow reuse.
|
@ -1,111 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.70**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the `pocketmine\network\mcpe` namespace are compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
### Highlights
|
||||
This version introduces support for a new, more advanced version of Timings.
|
||||
This improved system provides more detail than the old system, and supports being displayed in a tree view, making it much easier to see which timers contribute to which other timers.
|
||||
|
||||
In addition, some minor performance improvements have been made, along with a couple of minor API additions.
|
||||
|
||||
# 4.19.0
|
||||
Released 11th April 2023.
|
||||
|
||||
## General
|
||||
- Updated the Timings system.
|
||||
- Timings records now include parent information, allowing them to be displayed in a tree view (e.g. https://timings.pmmp.io/?id=303556).
|
||||
- Timings records now include additional information, such as Peak (max time spent on any single tick), and Ticks (number of ticks the timer was active on).
|
||||
- New timings have been added for every event.
|
||||
- A new timer `Player Network Send - Pre-Spawn Game Data` has been added, and covers most of the time spent handling `ResourcePackClientResponsePacket`, giving a clearer picture of what's happening.
|
||||
- Improved performance of the plugin event system.
|
||||
- By introducing some caching, the event system now has 90% less overhead than in previous versions.
|
||||
- Improved performance of the random chunk ticking system.
|
||||
- The selection of ticked random chunks, and their validation for ticking, is now cached. This significantly reduces the overhead of chunk selection.
|
||||
- Factions servers and other game modes with big maps and sparsely populated areas will see the most benefit from this change.
|
||||
- Real-world performance benefit of this change is anywhere from 0-20%, depending on server type and configuration.
|
||||
- The `timings paste` command now logs a debug message with the server response on failure to paste a timings report.
|
||||
|
||||
## API
|
||||
### `pocketmine\entity\object`
|
||||
- The following API constants have been added:
|
||||
- `ExperienceOrb::DEFAULT_DESPAWN_DELAY` - the default delay in ticks before an experience orb despawns
|
||||
- `ExperienceOrb::NEVER_DESPAWN` - magic value for `setDespawnDelay()` to make an experience orb never despawn
|
||||
- `ExperienceOrb::MAX_DESPAWN_DELAY` - the maximum delay in ticks before an experience orb despawns
|
||||
- The following API methods have been added:
|
||||
- `public ExperienceOrb->getDespawnDelay() : int` - returns the delay in ticks before this experience orb despawns
|
||||
- `public ExperienceOrb->setDespawnDelay(int $despawnDelay) : void` - sets the delay in ticks before this experience orb despawns
|
||||
- The following properties have been deprecated
|
||||
- `ExperienceOrb->age` - superseded by despawn delay methods
|
||||
|
||||
### `pocketmine\event`
|
||||
- The following API methods have been added:
|
||||
- `public HandlerList->getListenerList() : list<RegisteredListener>` - returns an ordered list of handlers to be called for the event
|
||||
|
||||
### `pocketmine\player`
|
||||
- The following API methods have behavioural changes:
|
||||
- `ChunkSelector->selectChunks()` now yields the distance in chunks from the center as the key, instead of an incrementing integer.
|
||||
- The following classes have been deprecated:
|
||||
- `PlayerChunkLoader` (this was technically internal, but never marked as such)
|
||||
|
||||
### `pocketmine\timings`
|
||||
- The following API constants have been deprecated:
|
||||
- `Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX` - this is superseded by timings group support (see `Timings::GROUP_BREAKDOWN`)
|
||||
- The following API constants have been added:
|
||||
- `Timings::GROUP_BREAKDOWN` - this group makes a timer appear in the `Minecraft - Breakdown` section of a timings report
|
||||
- The following API methods have been added:
|
||||
- `public TimingsHandler->getGroup() : string` - returns the name of the table in which this timer will appear in a timings report
|
||||
- The following API methods have changed signatures:
|
||||
- `TimingsHandler->__construct()` now accepts an additional, optional `string $group` parameter, which defaults to `Minecraft`.
|
||||
|
||||
### `pocketmine\world`
|
||||
#### Highlights
|
||||
Ticking chunks is now done using the `ChunkTicker` system, which has a much more fine-grained API than the old `TickingChunkLoader` system, as well as better performance.
|
||||
It works similarly to the `ChunkLoader` system, in that chunks will be ticked as long as at least one `ChunkTicker` is registered for them.
|
||||
|
||||
#### API changes
|
||||
- The following classes have been deprecated:
|
||||
- `TickingChunkLoader` - this has been superseded by the more powerful and performant `ChunkTicker` APIs
|
||||
- The following classes have been added:
|
||||
- `ChunkTicker` - an opaque object used for `registerTickingChunk()` to instruct the `World` that we want a chunk to be ticked
|
||||
- The following API methods have been added:
|
||||
- `public World->registerTickingChunk(ChunkTicker $ticker, int $chunkX, int $chunkZ) : void` - registers a chunk to be ticked by the given `ChunkTicker`
|
||||
- `public World->unregisterTickingChunk(ChunkTicker $ticker, int $chunkX, int $chunkZ) : void` - unregisters a chunk from being ticked by the given `ChunkTicker`
|
||||
|
||||
# 4.19.1
|
||||
Released 14th April 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed inventory rollbacks when spreading items in ender chests.
|
||||
- Fixed inventory rollbacks when shift-clicking to craft and the outputs would have been split across multiple inventory slots.
|
||||
- Fixed incorrect spawn terrain generation for newly created worlds.
|
||||
- Fixed `chunk-ticking.tick-radius` not disabling chunk ticking when set to `0`.
|
||||
- Fixed chunks not being ticked if they previously left a player's simulation distance without leaving their view distance.
|
||||
- Fixed height of collision boxes for Grass Path and Farmland blocks.
|
||||
|
||||
# 4.19.2
|
||||
Released 14th April 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed player timings duplication leading to extremely large timings reports when timings runs for a long time with many players.
|
||||
- Packet timings are now indexed by class FQN instead of packet ID. This prevents erroneous timer reuse on packet ID reuse (e.g. multi version servers).
|
||||
- Fixed entity timings being shared by different classes with the same short name. This led to incorrect timings being reported for some entities when custom entities were used.
|
||||
|
||||
# 4.19.3
|
||||
Released 21st April 2023.
|
||||
|
||||
## General
|
||||
- Error IDs for `Packet processing error` disconnects are now split into 4-character chunks to make them easier to type (since they can't be copied from the disconnection screen of a client).
|
||||
|
||||
## Fixes
|
||||
- Fixed entity-block intersections being checked twice per tick. Besides wasting CPU time, this may have caused unexpected behaviour during entity-block interactions with blocks like water or cacti.
|
||||
- Fixed performance issue in network inventory synchronization due item NBT being prepared twice.
|
||||
- Fixed `tools/simulate-chunk-selector.php` argument parsing being completely broken (weird behaviour of PHP `getopt()`).
|
||||
|
||||
## Internals
|
||||
- `TimingsHandler->stopTiming()` now logs an error message if a subtimer wasn't stopped, rather than throwing an exception.
|
||||
- Due to interactions between `try...finally` and unexpected errors, throwing exceptions made it difficult for plugin developers to debug errors in their plugins, since it obscured the original error.
|
@ -1,121 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.18.10**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.2.0
|
||||
- Added support for Minecraft: Bedrock Edition 1.18.10.
|
||||
|
||||
# 4.2.1
|
||||
Released 19th February 2022.
|
||||
|
||||
## General
|
||||
- Improved performance of `Item::nbtSerialize()` - this will improve performance during world saves.
|
||||
- Added more missing changes to the 4.0.0 changelog.
|
||||
|
||||
## Fixes
|
||||
- Fixed multiple players being able to sleep in the same bed.
|
||||
- Fixed hitbox not resetting properly after swimming or gliding.
|
||||
|
||||
# 4.2.2
|
||||
Released 2nd March 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed crash in `/dumpmemory` due to usage of non-printable string keys in `CraftingManager`. Array contents in memory dumps are now rendered as prettified key-value pairs.
|
||||
- Fixed output directory for `/dumpmemory`.
|
||||
- `PlayerInventory->isHotbarSlot()` now correctly returns `false` when given `9`.
|
||||
- Fixed ghost items left in the inventory when dropping tools while mining.
|
||||
|
||||
# 4.2.3
|
||||
Released 9th March 2022.
|
||||
|
||||
## Technical
|
||||
- Now analysed using PHPStan 1.4.8.
|
||||
- Now using `pocketmine/bedrock-protocol` [`8.0.1`](https://github.com/pmmp/BedrockProtocol/releases/tag/8.0.1%2Bbedrock-1.18.10).
|
||||
|
||||
## Fixes
|
||||
### Core
|
||||
- Fixed a memory leak and other bugs related to plugins disabling themselves during `onEnable()`.
|
||||
|
||||
### Gameplay
|
||||
- Sweet berry bushes now absorb fall damage.
|
||||
- Fixed mycelium spreading onto coarse dirt.
|
||||
- Fixed blocks placed during `Block->onIncinerate()` getting overwritten.
|
||||
- Fixed shulker boxes being unopenable when underwater.
|
||||
- Fixed invisible fire on top of transparent non-flammable blocks.
|
||||
|
||||
### API
|
||||
- Various APIs accepting `Vector3`, `Position` or `Location` no longer accept objects containing `INF` or `NaN` in any component. Previously, this was allowed, but would cause lots of obscure crashes later on.
|
||||
- `Entity->setRotation()` no longer accepts `INF` or `NaN`.
|
||||
- Fixed missing bounds check for `ItemFrame->setItemDropChance()`.
|
||||
|
||||
# 4.2.4
|
||||
Released 18th March 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed a crash when handling out-of-bounds meta values on the network.
|
||||
|
||||
# 4.2.5
|
||||
Released 28th March 2022.
|
||||
|
||||
## General
|
||||
- The layout of the human-readable part of crashdumps has been changed in an effort to improve the useful information density. It is hoped that this change will cause more useful information to be provided when people paste crash traces on Discord, since all the most important information is now at the top of the file.
|
||||
- Version, git hash, PHP version and OS have been moved to the top of the crashdump.
|
||||
- Backtrace has been moved above code sample.
|
||||
- Docker images are now built by GitHub Actions (first live test).
|
||||
|
||||
## Technical
|
||||
- The methods of `Inventory` and `BaseInventory` have been rearranged to improve coherency.
|
||||
|
||||
## Fixes
|
||||
### API
|
||||
- Enum members of enums created using `EnumTrait` are now able to have single-character names.
|
||||
- Registry members of registries created using `RegistryTrait` or `CloningRegistryTrait` now have their names checked for invalid characters.
|
||||
- `Entity::__construct()` now uses a guard variable to prevent it from being called multiple times unintentionally. This is necessary because `Entity::__construct()` has side effects.
|
||||
- Fixed `PlayerItemHeldEvent` not being called when the content of the held slot was changed (e.g. replacing the held item via inventory menu).
|
||||
|
||||
### Gameplay
|
||||
- Reduced the appearance of ghost items in unsupported gameplay scenarios using client prediction information. This fixes, for example, the appearance of ghost items when right-clicking on a filled flower pot.
|
||||
|
||||
# 4.2.6
|
||||
Released 1st April 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed buffer length underflow crash in `LoginPacket` handling.
|
||||
|
||||
# 4.2.7
|
||||
Released 15th April 2022.
|
||||
|
||||
## General
|
||||
- Added lots more documentation (in comments) about the `aliases` section in `pocketmine.yml`. You can read about this feature in the `aliases` section of the [updated `pocketmine.yml` template](/resources/pocketmine.yml).
|
||||
- Improved wording of documentation of `PlayerPreLoginEvent`.
|
||||
|
||||
## Fixes
|
||||
- Fixed core server crash when a plugin causes another plugin to be disabled during a scheduled task.
|
||||
- Fixed core server crash when loading a plugin with an abstract main class.
|
||||
- Fixed ghost items in many interaction situations (most notably, using projectiles while looking at an entity or block).
|
||||
- Implemented a workaround for a client teleport bug which led to player positions not updating properly when using ender pearls.
|
||||
- Fixed buggy movement when teleporting the player during `PlayerToggleSneakEvent`, `PlayerToggleSprintEvent`, `PlayerToggleSwimEvent` and `PlayerToggleGlideEvent`.
|
||||
|
||||
# 4.2.8
|
||||
Released 17th April 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed a memory leak in RakLib which could result in a server crash when players stay online for a long time.
|
||||
- Fixed server crash when attempting to load a corrupted empty resource pack.
|
||||
- Fixed users with the same name with differerently cased letters being able to duplicate items (userdata is matched by case-insensitive name).
|
||||
|
||||
# 4.2.9
|
||||
Released 19th April 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed several potential crashes when deserializing item NBT (due to insufficient validation of input data).
|
||||
|
||||
# 4.2.10
|
||||
Released 20th April 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed performance issue when chat messages received from the client contain many newlines. This security vulnerability was disclosed publicly necessitating a priority fix.
|
@ -1,79 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.80**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the `pocketmine\network\mcpe` namespace are compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
### Interim releases
|
||||
If you're upgrading from 4.17.x directly to 4.20.x, please also read the following changelogs, as the interim releases contain important changes:
|
||||
|
||||
- [4.18.0](https://github.com/pmmp/PocketMine-MP/blob/4.20.0/changelogs/4.18.md#4180) - major performance improvements, internal network changes, minor API additions
|
||||
- [4.19.0](https://github.com/pmmp/PocketMine-MP/blob/4.20.0/changelogs/4.19.md#4190) - minor performance improvements, improved timings system, minor API additions
|
||||
|
||||
# 4.20.0
|
||||
Released 26th April 2023.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.80.
|
||||
- Removed support for older versions.
|
||||
|
||||
## Fixes
|
||||
- Fixed packet processing error when attempting to use a stonecutter.
|
||||
- Fixed armor slots containing ghost items when cancelling right-click to equip armor.
|
||||
- Fixed crash in `HandlerList->getListenersByPriority()` when no listeners are registered at the given priority.
|
||||
|
||||
## API
|
||||
### `pocketmine\block`
|
||||
- The following API methods have been added:
|
||||
- `public BaseSign->getEditorEntityRuntimeId() : int` - returns the entity runtime ID of the player currently editing this sign, or `null` if none
|
||||
- `public BaseSign->setEditorEntityRuntimeId(?int $editorEntityRuntimeId) : $this` - sets the entity runtime ID of the player currently editing this sign
|
||||
|
||||
### `pocketmine\player`
|
||||
- The following API methods have been added:
|
||||
- `public Player->openSignEditor(Vector3 $position) : void` - opens the client-side sign editor GUI for the given position
|
||||
|
||||
# 4.20.1
|
||||
Released 27th April 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash when firing a bow while holding arrows in the offhand slot.
|
||||
|
||||
## Internals
|
||||
- `ItemStackContainerIdTranslator::translate()` now requires an additional `int $slotId` parameter and returns `array{int, int}` (translated window ID, translated slot ID) to be used with `InventoryManager->locateWindowAndSlot()`.
|
||||
- `InventoryManager->locateWindowAndSlot()` now checks if the translated slot actually exists in the requested inventory, and returns `null` if not. Previously, it would return potentially invalid slot IDs without checking them, potentially leading to crashes.
|
||||
|
||||
# 4.20.2
|
||||
Released 4th May 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed all types of wooden logs appearing as oak in the inventory.
|
||||
- Fixed a performance issue in `BaseInventory->canAddItem()` (missing `continue` causing useless logic to run).
|
||||
|
||||
# 4.20.3
|
||||
Released 6th May 2023.
|
||||
|
||||
## Improvements
|
||||
- Reduced memory usage of `RuntimeBlockMapping` from 25 MB to 9 MB. Since every thread has its own copy of the block map, this saves a substantial amount of memory.
|
||||
|
||||
## Fixes
|
||||
- Fixed players falling through blocks in spectator mode.
|
||||
- Fixed timings reports getting bloated by prolific usage of `PluginManager->registerEvent()`.
|
||||
- This was caused by creating a new timings handler for each call, regardless of whether a timer already existed for the given event and callback.
|
||||
- Fixed `Full Server Tick` and other records being missing from timings reports.
|
||||
- This was caused by timings handler depth not getting reset when timings was disabled and later re-enabled.
|
||||
|
||||
# 4.20.4
|
||||
Released 6th May 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed players being forced into flight mode in every game mode.
|
||||
- Moral of the story: do not assume anything in Mojang internals does what its name suggests...
|
||||
|
||||
# 4.20.5
|
||||
Released 30th May 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash due to a bug in upstream dependency [`netresearch/jsonmapper`](https://github.com/cweiske/JsonMapper).
|
@ -1,77 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.80**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the `pocketmine\network\mcpe` namespace, and don't use reflection or any internal methods,
|
||||
will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
# 4.21.0
|
||||
Released 17th May 2023.
|
||||
|
||||
## General
|
||||
- PHP 8.1 is now required. Most plugins should run without changes, but some might need to be updated due to language-level deprecations.
|
||||
- Ticking chunk count is now shown separately from loaded chunk count in the `/status` command, providing useful performance information.
|
||||
- Further improved performance of ticking chunk selection.
|
||||
- Improved performance of some inventory functions.
|
||||
- Reduced server memory footprint in most cases by ~9 MB per thread.
|
||||
- Due to large overhead, async network compression is now only used for packets larger than 10 KB by default.
|
||||
|
||||
## Configuration
|
||||
- Added the following new `pocketmine.yml` configuration options:
|
||||
- `network.async-compression-threshold` - minimum size of packet which will be compressed using `AsyncTask`
|
||||
- Default is 10 KB, which means that very few packets will use async compression in practice. This is because the overhead of compressing async is currently so high that it's not worth it for smaller packets.
|
||||
|
||||
## Timings
|
||||
- Timings reports no longer include the unused metadata fields `Entities` and `LivingEntities`.
|
||||
- Timings reports now correctly calculate the peak time of a timer.
|
||||
- Previously it was incorrectly recorded as the longest time spent in a single tick, rather than the longest time spent in a single activation.
|
||||
- Timings report version has been bumped to `2` to reflect this change.
|
||||
- All world-specific timers now have generic aggregate timings, making it much easier to locate performance patterns across all worlds.
|
||||
|
||||
## Gameplay
|
||||
- Players in spectator mode are no longer able to pick blocks, and now have finite resources similar to survival mode.
|
||||
|
||||
## API
|
||||
### `pocketmine\world`
|
||||
- The following API methods have been added:
|
||||
- `public World->getTickingChunks() : list<int>` - returns a list of chunk position hashes (a la `World::chunkHash()`) which are currently valid for random ticking
|
||||
|
||||
### `pocketmine\inventory`
|
||||
- The following API methods have been added:
|
||||
- `protected BaseInventory->getMatchingItemCount(int $slot, Item $test, bool $checkDamage, bool $checkTags) : int` - returns the number of items in the given stack if the content of the slot matches the test item, or zero otherwise
|
||||
- This should be overridden if directly extending `BaseInventory` to provide a performance-optimised version. A slow default implementation is provided, but it will be removed in the future.
|
||||
|
||||
## Internals
|
||||
### Entity
|
||||
- Unused `NameTag` tag is no longer saved for `Human` entities.
|
||||
|
||||
### Inventory
|
||||
- `BaseInventory` now uses a new internal method `getMatchingItemCount()` to locate items in the inventory without useless cloning. This improves performance of various API methods, such as `addItem()`, `contains()`, and more.
|
||||
- Specialization of `Inventory->isSlotEmpty()` in `BaseInventory` subclasses has been added to improve performance of some API methods.
|
||||
|
||||
### Network
|
||||
- `RuntimeBlockMapping` no longer keeps all block palette NBT data in memory.
|
||||
- This significantly reduces server idle memory footprint.
|
||||
- For multi-version implementations, this will have a significant impact on memory usage, since a different block palette is often required to support each version.
|
||||
- NBT will be lazy-loaded into memory and cached if `getBedrockKnownStates()` is called. However, this is not used by PocketMine-MP under normal circumstances.
|
||||
- Removed unnecessary usage of `Utils::validateCallableSignature()` from some internal network pathways, improving performance.
|
||||
|
||||
### Scheduler
|
||||
- `AsyncPool` no longer double-checks progress updates on completed tasks.
|
||||
|
||||
### World
|
||||
- Ticking chunks are now tracked in `World->validTickingChunks` and `World->recheckTickingChunks`.
|
||||
- This allows avoiding rechecking every ticking chunk for validity during ticking chunk selection, improving performance.
|
||||
- In some cases, this allows bypassing chunk selection entirely, reducing selection cost to zero.
|
||||
- Registered but ineligible ticking chunks are no longer rechecked every tick.
|
||||
- This was causing wasted cycles during async worker backlog.
|
||||
- The internal system must call `markTickingChunkForRecheck()` whenever a ticking chunk's eligibility for ticking has potentially changed, rather than just when it has changed from a yes to a no.
|
||||
|
||||
# 4.21.1
|
||||
Released 30th May 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash due to a bug in upstream dependency [`netresearch/jsonmapper`](https://github.com/cweiske/JsonMapper).
|
@ -1,77 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.18.30**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.3.0
|
||||
Released 20th April 2022.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.18.30.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.3.1
|
||||
Released 23rd April 2022.
|
||||
|
||||
## Fixes
|
||||
- Updated BedrockProtocol dependency to fix incorrect command argument types.
|
||||
- Creative players no longer die in the void.
|
||||
|
||||
# 4.3.2
|
||||
Released 10th May 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed an assertion failure in certain edge cases during world generation.
|
||||
- Fixed `Entity::setNameTagVisible()` not immediately showing results to players already online.
|
||||
|
||||
## Documentation
|
||||
- Added more documentation in the template `pocketmine.yml` for the `aliases` config section.
|
||||
- Removed useless doc comment in `PlayerChangeSkinEvent`.
|
||||
|
||||
# 4.3.3
|
||||
Released 16th May 2022.
|
||||
|
||||
## General
|
||||
- Improved display of parameters in exception stack trace logs.
|
||||
- Exception stack traces now include names for dynamic named arguments (i.e. arguments that don't match any parameter of the function), if any were given.
|
||||
- Note: Named arguments which do match parameters are not shown this way, since PHP reduces them to positional arguments for performance reasons.
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash when chunks are unloaded during chunk generation callbacks
|
||||
- Fixed dead coral fan items placing coral fans in the wrong orientation.
|
||||
- Fixed max stack size of boat items.
|
||||
|
||||
# 4.3.4
|
||||
Released 22nd May 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed `difficulty` in `server.properties` having no effect - it's now applied to newly generated worlds.
|
||||
- Note: this setting still doesn't behave the same way as vanilla due to potential disruption to existing servers.
|
||||
- Fixed paintings not working in newly generated worlds and some other cases.
|
||||
- Fixed inventory window switching breaking the inventory UI in some cases (e.g. pressing E while clicking a chest).
|
||||
- Fixed minecart items incorrectly stacking.
|
||||
- Fixed incorrect light levels in translucent blocks at the top of the world.
|
||||
- Fixed teleporting sleeping players causing broken behaviour on the sleeping player's client.
|
||||
- Fixed `EntityExplodeEvent->setYield()` accepting values outside the range 0-100.
|
||||
- Fixed `ExplosionPrimeEvent->setForce()` accepting negative values (later resulting in crashes).
|
||||
|
||||
## Documentation
|
||||
- Updated documentation for the following events:
|
||||
- `CommandEvent`
|
||||
- `EntityDespawnEvent`
|
||||
- `EntityExplodeEvent`
|
||||
- `EntitySpawnEvent`
|
||||
- `ExplosionPrimeEvent`
|
||||
- `InventoryTransactionEvent`
|
||||
- `ItemDespawnEvent`
|
||||
- `ItemSpawnEvent`
|
||||
- `PlayerCommandPreprocessEvent`
|
||||
- `PlayerDropItemEvent`
|
||||
- `PlayerItemHeldEvent`
|
||||
- `PlayerKickEvent`
|
||||
- `PlayerQuitEvent`
|
||||
- `PlayerTransferEvent`
|
||||
- `UpdateNotifyEvent`
|
@ -1,77 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.18.30**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.4.0-BETA1
|
||||
Released 25th May 2022.
|
||||
|
||||
## General
|
||||
- The server will now shut itself down if any of the following errors occur during startup:
|
||||
- Any plugin fails to load or enable (plugins loaded by other plugins post-startup are **not** affected by this change) (**PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)**)
|
||||
- The motivation for this change is to prevent situations where plugins failing to load could result in adverse outcomes, such as a world protection plugin leaving a lobby unprotected from griefing.
|
||||
- If you encounter this problem, remove the offending plugin(s) or prevent it from loading using `plugin_list.yml`.
|
||||
- See **PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)** for more detail on this change.
|
||||
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to load (worlds loaded by plugins are **not** affected by this change)
|
||||
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to generate (e.g. due to invalid generator settings)
|
||||
- Enabling the server whitelist while the server is running (e.g. using `/whitelist on`) will now kick any non-whitelisted players currently on the server (**PR [#4774](https://github.com/pmmp/PocketMine-MP/pull/4774)**).
|
||||
- Help for commands (`/help <name of command>`) now displays a list of aliases of that command.
|
||||
- A CRITICAL log message is now generated if a plugin disables itself when enabling, in case the plugin doesn't emit any error of its own.
|
||||
- The `/give` command now shows the alias used to find the given item in the success message, instead of the item ID/meta.
|
||||
|
||||
## Fixes
|
||||
- Block placement has been fixed in many places where it previously didn't work correctly (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**):
|
||||
- torches on top of slabs, upside-down stairs
|
||||
- torches on the back face of stairs
|
||||
- flower pots on top of fences
|
||||
- the list goes on and on ...
|
||||
- Fixed backslash escapes not getting properly removed from commands in some cases.
|
||||
- Fixed aliases defined in the `aliases` section of `pocketmine.yml` not being treated as quote-aware.
|
||||
|
||||
## Gameplay
|
||||
- Plants in flower pots can now be removed by right-clicking on the flower pot.
|
||||
- Leaves now have a 2% chance of dropping sticks when destroyed by hand (**PR [#5019](https://github.com/pmmp/PocketMine-MP/pull/5019)**).
|
||||
- Food exhaustion now matches Bedrock 1.18.30 (**PR [#5034](https://github.com/pmmp/PocketMine-MP/pull/5034)**).
|
||||
- Implemented Stonecutter block (**PR [#4732](https://github.com/pmmp/PocketMine-MP/pull/4732)**).
|
||||
|
||||
## API
|
||||
### Block
|
||||
- Added `Block->getSupportType(Facing) : SupportType` (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||
- This is used to determine the kind of support a block face can provide to a block (e.g. a torch) placed on it.
|
||||
- Added `utils\SupportType` enum (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||
- `tile\Spawnable->isDirty()` and `tile\Spawnable->setDirty()` are now `@deprecated`.
|
||||
|
||||
### Command
|
||||
- Added `CommandStringHelper::parseQuoteAware()`. This static method contains the code used by `SimpleCommandMap` used to parse quoted command arguments.
|
||||
|
||||
### Entity
|
||||
- Added `Human::emote()` (**PR [#4610](https://github.com/pmmp/PocketMine-MP/pull/4610)**)
|
||||
|
||||
### Event
|
||||
- `PlayerCommandPreprocessEvent` is now `@deprecated`, since its functionality is entirely replaced by other, general-purpose events.
|
||||
- Use `CommandEvent` to intercept commands.
|
||||
- Use `PlayerChatEvent` to intercept chat messages.
|
||||
- To convert a chat message into a command, pass it directly to `Server->dispatchCommand()` with the player as sender.
|
||||
- Added `PlayerPostChunkSendEvent` (**PR [#4937](https://github.com/pmmp/PocketMine-MP/pull/4937)**).
|
||||
- Added `PlayerDeathEvent->setKeepXp()` (**PR [#4015](https://github.com/pmmp/PocketMine-MP/pull/4015)**).
|
||||
- `InventoryCloseEvent` is now called **after** the target window has been removed. This fixes various feedback loops caused by trying to open new windows to a player while there was one still active.
|
||||
- As a side effect, this now means that `Player->getCurrentWindow()` will return `null` during `InventoryCloseEvent`. Use `InventoryCloseEvent->getInventory()` instead.
|
||||
|
||||
### Item
|
||||
- `StringToItemParser` now recognizes `cod`, `raw_cod` and `cooked_cod` aliases.
|
||||
|
||||
### Plugin
|
||||
- `DisablePluginException` may now be thrown from `Plugin::onEnable()` to make the server gracefully disable the plugin (without crashing) (**PR [#4780](https://github.com/pmmp/PocketMine-MP/pull/4780)**).
|
||||
- `PluginManager->registerEvent()` now returns the `RegisteredListener` created for the handler, to permit unregistering it later.
|
||||
|
||||
## Internals
|
||||
- Private property declarations now use typed properties (PHP 7.4) and promoted constructor properties (PHP 8.0) wherever possible.
|
||||
- Protected and public properties remain unchanged, since they can't be changed without breaking subclasses.
|
||||
- Promoted constructor properties are only used when it's consistently possible to promote most or all properties in a class.
|
||||
- Simplified and improved legibility of `FormattedCommandAlias`.
|
||||
- Added unit tests for the quote-aware command parser used by `SimpleCommandMap`.
|
||||
- Various hardcoded values in `block` package classes have been moved to private constants to improve readability.
|
||||
- Added various constants used in the `LevelDB` world provider.
|
@ -1,97 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.18.30**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.4.0
|
||||
Released 1st June 2022.
|
||||
|
||||
## General
|
||||
- The server will now shut itself down if any of the following errors occur during startup:
|
||||
- Any plugin fails to load or enable (plugins loaded by other plugins post-startup are **not** affected by this change) (**PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)**)
|
||||
- The motivation for this change is to prevent situations where plugins failing to load could result in adverse outcomes, such as a world protection plugin leaving a lobby unprotected from griefing.
|
||||
- If you encounter this problem, remove the offending plugin(s) or prevent it from loading using `plugin_list.yml`.
|
||||
- See **PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)** for more detail on this change.
|
||||
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to load (worlds loaded by plugins are **not** affected by this change)
|
||||
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to generate (e.g. due to invalid generator settings)
|
||||
- Enabling the server whitelist while the server is running (e.g. using `/whitelist on`) will now kick any non-whitelisted players currently on the server (**PR [#4774](https://github.com/pmmp/PocketMine-MP/pull/4774)**).
|
||||
- Help for commands (`/help <name of command>`) now displays a list of aliases of that command.
|
||||
- A CRITICAL log message is now generated if a plugin disables itself when enabling, in case the plugin doesn't emit any error of its own.
|
||||
- The `/give` command now shows the alias used to find the given item in the success message, instead of the item ID/meta.
|
||||
|
||||
## Fixes
|
||||
- Block placement has been fixed in many places where it previously didn't work correctly (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**):
|
||||
- torches on top of slabs, upside-down stairs
|
||||
- torches on the back face of stairs
|
||||
- flower pots on top of fences
|
||||
- the list goes on and on ...
|
||||
- Fixed backslash escapes not getting properly removed from commands in some cases.
|
||||
- Fixed aliases defined in the `aliases` section of `pocketmine.yml` not being treated as quote-aware.
|
||||
|
||||
## Gameplay
|
||||
- Plants in flower pots can now be removed by right-clicking on the flower pot.
|
||||
- Leaves now have a 2% chance of dropping sticks when destroyed by hand (**PR [#5019](https://github.com/pmmp/PocketMine-MP/pull/5019)**).
|
||||
- Food exhaustion now matches Bedrock 1.18.30 (**PR [#5034](https://github.com/pmmp/PocketMine-MP/pull/5034)**).
|
||||
- Implemented Stonecutter block (**PR [#4732](https://github.com/pmmp/PocketMine-MP/pull/4732)**).
|
||||
|
||||
## API
|
||||
### Block
|
||||
- Added `Block->getSupportType(Facing) : SupportType` (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||
- This is used to determine the kind of support a block face can provide to a block (e.g. a torch) placed on it.
|
||||
- Added `utils\SupportType` enum (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
|
||||
- `tile\Spawnable->isDirty()` and `tile\Spawnable->setDirty()` are now `@deprecated`.
|
||||
|
||||
### Command
|
||||
- Added `CommandStringHelper::parseQuoteAware()`. This static method contains the code used by `SimpleCommandMap` used to parse quoted command arguments.
|
||||
|
||||
### Entity
|
||||
- Added `Human::emote()` (**PR [#4610](https://github.com/pmmp/PocketMine-MP/pull/4610)**)
|
||||
|
||||
### Event
|
||||
- `PlayerCommandPreprocessEvent` is now `@deprecated`, since its functionality is entirely replaced by other, general-purpose events.
|
||||
- Use `CommandEvent` to intercept commands.
|
||||
- Use `PlayerChatEvent` to intercept chat messages.
|
||||
- To convert a chat message into a command, pass it directly to `Server->dispatchCommand()` with the player as sender.
|
||||
- Added `PlayerPostChunkSendEvent` (**PR [#4937](https://github.com/pmmp/PocketMine-MP/pull/4937)**).
|
||||
- Added `PlayerDeathEvent->setKeepXp()` (**PR [#4015](https://github.com/pmmp/PocketMine-MP/pull/4015)**).
|
||||
- `InventoryCloseEvent` is now called **after** the target window has been removed. This fixes various feedback loops caused by trying to open new windows to a player while there was one still active.
|
||||
- As a side effect, this now means that `Player->getCurrentWindow()` will return `null` during `InventoryCloseEvent`. Use `InventoryCloseEvent->getInventory()` instead.
|
||||
|
||||
### Item
|
||||
- `StringToItemParser` now recognizes `cod`, `raw_cod` and `cooked_cod` aliases.
|
||||
|
||||
### Plugin
|
||||
- `DisablePluginException` may now be thrown from `Plugin::onEnable()` to make the server gracefully disable the plugin (without crashing) (**PR [#4780](https://github.com/pmmp/PocketMine-MP/pull/4780)**).
|
||||
- `PluginManager->registerEvent()` now returns the `RegisteredListener` created for the handler, to permit unregistering it later.
|
||||
|
||||
## Internals
|
||||
- Private property declarations now use typed properties (PHP 7.4) and promoted constructor properties (PHP 8.0) wherever possible.
|
||||
- Protected and public properties remain unchanged, since they can't be changed without breaking subclasses.
|
||||
- Promoted constructor properties are only used when it's consistently possible to promote most or all properties in a class.
|
||||
- Simplified and improved legibility of `FormattedCommandAlias`.
|
||||
- Added unit tests for the quote-aware command parser used by `SimpleCommandMap`.
|
||||
- Various hardcoded values in `block` package classes have been moved to private constants to improve readability.
|
||||
- Added various constants used in the `LevelDB` world provider.
|
||||
|
||||
# 4.4.1
|
||||
Released 5th June 2022.
|
||||
|
||||
## General
|
||||
- The server process will now exit with an error code if plugins, worlds or network interfaces failed to start.
|
||||
|
||||
## Fixes
|
||||
- Fixed graylisted plugins preventing the server from starting.
|
||||
- Fixed `composer make-devtools` command.
|
||||
- Fixed the `Maximum memory (manager)` units being incorrectly displayed in `/status`.
|
||||
- Fixed `Player->removeCurrentWindow()` breaking inventory windows.
|
||||
|
||||
# 4.4.2
|
||||
Released 7th June 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed a crash when arbitrary item IDs appeared in network items in some cases.
|
||||
- Fixed saved paintings being deleted when loaded from disk (regression from 4.3.4).
|
||||
- Fixed max stack size of fishing rods.
|
@ -1,28 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.0**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.5.0
|
||||
Released 7th June 2022.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.0.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.5.1
|
||||
Released 8th June 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed commands defined in `pocketmine.yml` `aliases` not passing the correct arguments.
|
||||
- Updated BedrockProtocol to fix command argument types displayed on client-side command suggestions.
|
||||
|
||||
# 4.5.2
|
||||
Released 29th June 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed terrain getting redrawn when flying in spectator mode (or when using `Player->setHasBlockCollision(false)`).
|
||||
- Fixed skulls with the `noDrops` flag set being treated as unknown blocks.
|
@ -1,42 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.10**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.6.0
|
||||
Released 13th July 2022.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.10.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.6.1
|
||||
Released 22nd July 2022.
|
||||
|
||||
## Tools
|
||||
- `build/generate-registry-annotations.php` now supports processing single files (useful for PhpStorm file watchers).
|
||||
|
||||
## API
|
||||
- Updated documentation for `AsyncTask`.
|
||||
|
||||
## Fixes
|
||||
- Fixed incorrect items being displayed in item frames.
|
||||
- Fixed books not showing in lecterns.
|
||||
- Fixed incorrect damage interval of Wither status effect.
|
||||
- Fixed incorrect fire ticks when being set on fire by lava (8 seconds in Bedrock instead of 15).
|
||||
- `Entity->attack()` now cancels damage from `FIRE` and `FIRE_TICK` damage causes if the entity is fireproof.
|
||||
- Fixed inventory windows getting force-closed when the client attempts to use an enchanting table or anvil.
|
||||
|
||||
# 4.6.2
|
||||
Released 6th August 2022.
|
||||
|
||||
## Core
|
||||
- Improved server-side performance of `PlayerAuthInputPacket` handler.
|
||||
- Improved client-side performance of `FloatingTextParticle` by using an invisible falling block entity. This offered a roughly 5x performance improvement over using tiny invisible players in local testing.
|
||||
|
||||
## Fixes
|
||||
- Fixed assert failures and debug spam on debug Minecraft clients related to abilities in `AddPlayerPacket`.
|
||||
- Fixed crash in `ReversePriorityQueue` on PHP 8.1 by adding `#[ReturnTypeWillChange]` attribute.
|
@ -1,46 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.20**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.7.0
|
||||
Released 9th August 2022.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.20.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.7.1
|
||||
Released 14th August 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash when loading items from disk which have negative meta values.
|
||||
- Fixed Turtle Master potions not giving any effects.
|
||||
- Unimplemented items are no longer craftable.
|
||||
- Fixed incorrect items appearing in item frames (due to an obsolete workaround for 1.19.10).
|
||||
|
||||
# 4.7.2
|
||||
Released 16th August 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed crash when processing player skins with invalid geometry data.
|
||||
- Fixed spectator players being able to pick blocks using mousewheel click.
|
||||
- Improved supporting requirements for sugarcane.
|
||||
|
||||
# 4.7.3
|
||||
Released 22nd August 2022.
|
||||
|
||||
## General
|
||||
- Added complete translations for Spanish and Vietnamese.
|
||||
- All continuous integration (static analysis, unit tests, integration tests) are now performed on PHP 8.1 as well as 8.0.
|
||||
- InventoryTransaction now verifies that stack sizes of items after the transaction don't exceed the maximum stack size of the item type or the containing inventory.
|
||||
|
||||
## Fixes
|
||||
- Fixed Normal generator crash on PHP 8.1.
|
||||
- Fixed a race condition during async worker shutdown that could lead to tasks executing in the wrong order. This (very rarely) led to a crash in `PopulationTask` due to its preceding `GeneratorRegisterTask` not being executed.
|
||||
- Fixed `/give` accepting negative amounts or amounts larger than 32767 (vanilla max).
|
||||
- Fixed placement conditions for vines (no longer able to be placed on the side of cacti).
|
||||
- Fixed incorrect documentation of `SignText::__construct()`.
|
@ -1,23 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.21**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.8.0
|
||||
Released 24th August 2022.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.21.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.8.1
|
||||
Released 26th August 2022.
|
||||
|
||||
## General
|
||||
- Crashdumps now include JIT mode information for use by the Crash Archive.
|
||||
|
||||
## Fixes
|
||||
- Fixed uninitialized offset error in `DyeColorIdMap` when given invalid dye color IDs.
|
@ -1,36 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.30**
|
||||
|
||||
### Note about API versions
|
||||
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||
|
||||
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||
|
||||
# 4.9.0
|
||||
Released 20th September 2022.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.19.30.
|
||||
- Removed support for older versions.
|
||||
|
||||
# 4.9.1
|
||||
Released 11th October 2022.
|
||||
|
||||
## Documentation
|
||||
- Added and improved documentation for many API methods in `Player` and `Block`.
|
||||
- Added missing `@internal` tag for `TaskHandler->setNextRun()`, `TaskHandler->remove()` and `TaskHandler->run()`.
|
||||
|
||||
## Fixes
|
||||
- Flight state is now locked by the server in spectator mode. This prevents any attempt by the client to toggle flight mode.
|
||||
- Fixed entity health exceeding its max health after the expiry of Health Boost effect.
|
||||
- Fixed burp sound not being played when a player eats food.
|
||||
- Fixed placement conditions for mushrooms - they can now only be placed when the light level at the target is <= 12, or on podzol or mycelium.
|
||||
- Fixed sign text appearing to change colour and/or glow when using dye on a sign - since this feature is not yet implemented, no change should occur.
|
||||
- Fixed players drowning when sprint-swimming on the surface of water.
|
||||
|
||||
## Internals
|
||||
- Added more detailed debug logging during the player login sequence.
|
||||
- Silenced debug spam during `PreSpawnPacketHandler`, considerably reducing debug noise when players join.
|
||||
- Fixed an edge case in `InventoryManager->removeWindow()`. This bug didn't have any effect on stable versions, but caused a `next-minor` development version to crash.
|
||||
- `Item`s returned by event getters are now cloned if modifying the result will have no useful side effects.
|
||||
- Updated `pocketmine/bedrock-data` to [`1.11.1`](https://github.com/pmmp/BedrockData/tree/1.11.1%2Bbedrock-1.19.30), which reduces bandwidth consumption during logins by not sending useless biome generation data.
|
File diff suppressed because it is too large
Load Diff
@ -1,215 +0,0 @@
|
||||
**For Minecraft: Bedrock Edition 1.19.62**
|
||||
|
||||
5.0.0 is a major update to PocketMine-MP, including many new features and API changes. It is **not** compatible with plugins written for previous versions of PocketMine-MP.
|
||||
|
||||
**During the beta phase, no new features will be added.**
|
||||
|
||||
This stage of development is focused on stability and cleaning up any major issues introduced during the alpha stage.
|
||||
|
||||
## WARNING
|
||||
**This is a BETA release.** This means that it may be unstable, and is not yet ready for production use.
|
||||
|
||||
Since this version has undergone substantial changes compared to 4.x, plugins written for 4.x will need to be updated to work on this version.
|
||||
|
||||
Breaking API changes may still occur during the beta phase, but only if they are strictly necessary to fix a problem prior to full release.
|
||||
|
||||
**BACK UP your data before testing this.** This version will work with worlds and player data from 4.x,
|
||||
BUT any world or player data loaded in 5.0.0 will not work in 4.x due to backwards-incompatible storage format changes.
|
||||
|
||||
# 5.0.0-BETA1
|
||||
Released 7th March 2023.
|
||||
|
||||
**This release includes changes from the following releases:**
|
||||
- [All 5.0.0 alpha releases](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA1/changelogs/5.0-alpha.md)
|
||||
- [4.15.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA1/changelogs/4.15.md#4152)
|
||||
- [4.15.3](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA1/changelogs/4.15.md#4153)
|
||||
- [4.16.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA1/changelogs/4.16.md#4160)
|
||||
|
||||
## API
|
||||
### `pocketmine\block`
|
||||
- Improved documentation for the following methods:
|
||||
- `Block->getTypeId()`
|
||||
- `Block->getStateId()`
|
||||
- `Block->describeType()`
|
||||
- `Block->describeState()`
|
||||
|
||||
### `pocketmine\command`
|
||||
- The following API methods have been renamed:
|
||||
- `Command->getPermission()` -> `Command->getPermissions()`
|
||||
|
||||
## Internals
|
||||
- The following methods have been renamed:
|
||||
- `Block->computeStateData()` -> `Block->computeTypeAndStateData()`
|
||||
- `Block->decodeStateData()` -> `Block->decodeTypeAndStateData()`
|
||||
- Wall state data now packs connections into 7 bits instead of 8.
|
||||
|
||||
# 5.0.0-BETA2
|
||||
Released 11th April 2023.
|
||||
|
||||
**This release includes changes from the following releases:**
|
||||
- [4.17.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.17.md#4170)
|
||||
- [4.17.1](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.17.md#4171)
|
||||
- [4.17.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.17.md#4172)
|
||||
- [4.18.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.18.md#4180)
|
||||
- [4.18.1](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.18.md#4181)
|
||||
- [4.18.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.18.md#4182)
|
||||
- [4.18.3](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.18.md#4183)
|
||||
- [4.18.4](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.18.md#4184)
|
||||
- [4.19.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA2/changelogs/4.19.md#4190)
|
||||
|
||||
## Tools
|
||||
- Added script `tools/generate-bedrock-data-from-packets.php`. This tool accepts a txt file containing base64-encoded packet dumps.
|
||||
- This script has been used to generate data for [BedrockData](https://github.com/pmmp/BedrockData) for several years, but has only now been open-sourced.
|
||||
- It's used to generate data such as crafting recipes, creative inventory data, and various other blobs of data needed to support the current version of Minecraft: Bedrock Edition.
|
||||
|
||||
## Gameplay
|
||||
- Anvils now damage entities when they fall on top of them.
|
||||
|
||||
## API
|
||||
### `pocketmine\block\utils`
|
||||
- The following API interface requirements have been added (BC breaking):
|
||||
- `public Fallable->getFallDamagePerBlock() : float` (default implementation provided by `FallableTrait`)
|
||||
- `public Fallable->getMaxFallDamage() : float` (default implementation provided by `FallableTrait`)
|
||||
|
||||
### `pocketmine\data\bedrock\block`
|
||||
- The following new API methods have been added:
|
||||
- `public BlockStateData->getVersionAsString() : string`
|
||||
|
||||
#### `pocketmine\data\bedrock\block\upgrade\model`
|
||||
- `BlockStateUpgradeSchemaModelBlockRemap` now accepts `null` for `oldState` and `newState`. This makes it easier to generate portable schemas for other languages to read.
|
||||
|
||||
### `pocketmine\event\entity`
|
||||
- The following new API constants have been added:
|
||||
- `EntityDamageEvent::CAUSE_FALLING_BLOCK`
|
||||
- `EntityDamageEvent::MODIFIER_ARMOR_HELMET`
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following API methods have signature changes:
|
||||
- `ItemTypeIds::toBlockTypeId()` may now return `null` if the item type ID is not a block.
|
||||
|
||||
### `pocketmine\player`
|
||||
- The following classes have been removed:
|
||||
- `PlayerChunkLoader` - deprecated in 4.19.0 (this was technically internal, but never marked as such)
|
||||
|
||||
## Internals
|
||||
- Make use of `Item->canStackWith()` instead of `Item->equals()` wherever possible, to make the code more readable.
|
||||
|
||||
# 5.0.0-BETA3
|
||||
Released 17th May 2023.
|
||||
|
||||
**This release includes changes from the following releases:**
|
||||
- [4.19.1](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.19.md#4191)
|
||||
- [4.19.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.19.md#4192)
|
||||
- [4.19.3](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.19.md#4193)
|
||||
- [4.20.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4200)
|
||||
- [4.20.1](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4201)
|
||||
- [4.20.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4202)
|
||||
- [4.20.3](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4203)
|
||||
- [4.20.4](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4204)
|
||||
- [4.21.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.21.md#4210)
|
||||
|
||||
## General
|
||||
- Improved light propagation performance by 10-15%.
|
||||
|
||||
## Fixes
|
||||
- Fixed late initialization of coral type in `BaseCoral`.
|
||||
|
||||
## Tools
|
||||
- `tools/generate-blockstate-upgrade-schema.php` has the following improvements:
|
||||
- Now generates better errors when inconsistent blockstate versions are encountered.
|
||||
- Now generates more stable outputs when re-run on the same input.
|
||||
- Output now uses `copiedState` in `remappedStates` where possible. This significantly reduces the size of the output for blocks with partially flattened states.
|
||||
|
||||
## Gameplay
|
||||
- The following blocks have been added:
|
||||
- Cave Vines
|
||||
- The following items have been added:
|
||||
- Glow Berries
|
||||
- Mangrove Boat (incomplete)
|
||||
- Fixed flower pots being able to be placed inside flower pots.
|
||||
|
||||
## API
|
||||
### `pocketmine\block`
|
||||
- The following API methods have been renamed:
|
||||
- `Block->isSameType()` -> `Block->hasSameTypeId()`
|
||||
- `Block->describeType()` -> `Block->describeBlockItemState()`
|
||||
- `Block->describeState()` -> `Block->describeBlockOnlyState()`
|
||||
- The following API methods have been removed:
|
||||
- `Block->getRequiredTypeDataBits()`
|
||||
- `Block->getRequiredStateDataBits()`
|
||||
- The following API methods have been added:
|
||||
- `public Block->generateStatePermutations() : \Generator<int, Block, void, void>` - yields all possible states this block type can be in (used for `RuntimeBlockStateRegistry`)
|
||||
- The following API methods have signature changes:
|
||||
- `Sapling::__construct()` now accepts `SaplingType $saplingType` instead of `TreeType $treeType`
|
||||
- `RuntimeBlockStateRegistry->register()` no longer accepts an `$override` parameter.
|
||||
- The following classes have been added:
|
||||
- `utils\SaplingType` - enum of all sapling types
|
||||
- `utils\TreeType` has been moved to `pocketmine\world\generator\object` namespace.
|
||||
|
||||
### `pocketmine\data\bedrock\item\upgrade`
|
||||
- The following API methods have been added:
|
||||
- `public ItemIdMetaUpgrader->getSchemas() : array<int, BlockStateUpgradeSchema>` - returns a list of loaded schemas indexed by schema ID
|
||||
- `public ItemIdMetaUpgradeSchema->getRenamedIds() : array<string, string>` - returns a map of old ID -> new ID
|
||||
- `public ItemIdMetaUpgradeSchema->getRemappedMetas() : array<string, array<int, string>>` - returns a map of old ID -> list of old meta -> new ID
|
||||
|
||||
### `pocketmine\event\block`
|
||||
- The following API methods have been added:
|
||||
- `public BlockGrowEvent->getPlayer() : ?Player` - returns the player that triggered the block growth, or `null` if it was not triggered by a player
|
||||
- The following API methods have signature changes:
|
||||
- `BlockGrowEvent::__construct()` now accepts an optional `?Player $player` parameter.
|
||||
|
||||
### `pocketmine\event\world`
|
||||
- The following classes have been added:
|
||||
- `WorldDisplayNameChangeEvent` - called when a world's display name is changed
|
||||
|
||||
### `pocketmine\item`
|
||||
- `Boat` now uses a new `BoatType` enum instead of `TreeType`. This is because not all tree types have an associated boat type, and some boat types are not made from tree materials (e.g. bamboo raft).
|
||||
- The following API methods have been removed:
|
||||
- `Boat->getWoodType()`
|
||||
- The following API methods have been added:
|
||||
- `public Boat->getType() : BoatType`
|
||||
- `public Item->getStateId() : int` - returns an encoded ID containing the item type ID and encoded item state
|
||||
- The following API methods have been renamed:
|
||||
- `Item->describeType()` -> `Item->describeState()`
|
||||
- The following classes have been added:
|
||||
- `BoatType` - enum of all boat types
|
||||
- The following API methods have signature changes:
|
||||
- `BoatType::__construct()` now accepts `BoatType $boatType` instead of `TreeType $woodType`.
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following API methods have been added:
|
||||
- `public World->setDisplayName(string $name) : void`
|
||||
|
||||
### `pocketmine\world\format`
|
||||
- Fixed outdated documentation for various methods of `Chunk`.
|
||||
|
||||
### `pocketmine\world\format\io\data`
|
||||
- The following API interface requirements have been added:
|
||||
- `public WorldData->setDisplayName(string $value) : void`
|
||||
|
||||
## Internals
|
||||
- Reduced global usage in world providers. In the future, we want to have blockstate deserializers etc. injected rather than being global singletons.
|
||||
- `BlockStateUpgrader` now always updates the blockstate version, even if no changes were made. PM itself doesn't require this, but it's useful for tools to know whether to upgrade the data again (e.g. in testing scenarios).
|
||||
- `BlockStateDictionary` memory usage is now reduced from 9 MB to 3.5 MB using various techniques, including string reuse and binary-encoded states.
|
||||
- `RuntimeBlockMapping` has been renamed to `BlockTranslator`.
|
||||
- Singletons in the `pocketmine\network\mcpe\convert` package have been centralized under `TypeConverter`. In the future, this will be injected where needed, allowing different converters to be used for different sessions (useful for multiversion).
|
||||
- Overriding of serializers and deserializers of items and blocks is now consistently disallowed. Due to the lack of a good reason to allow overriding built-in blocks and items, this is no longer allowed.
|
||||
|
||||
# 5.0.0-BETA4
|
||||
Released 23rd May 2023.
|
||||
|
||||
## General
|
||||
- [`ext-pmmpthread` version 6.0.0](https://github.com/pmmp/ext-pmmpthread/releases/6.0.0) (renamed from `ext-pthreads`) is now required. This version has API changes compared to pthreads v5. Please read the linked changelog for details.
|
||||
- [`pocketmine/snooze` version 0.5.0](https://github.com/pmmp/Snooze/releases/0.5.0) is now required.
|
||||
- `pocketmine/classloader` and `pocketmine/log-pthreads` packages have been removed. The relevant classes from these packages are now included in-house in the `pocketmine/thread` namespace.
|
||||
- `BaseClassLoader` is replaced with `pocketmine\thread\ThreadSafeClassLoader`
|
||||
- `ThreadedLogger` is replaced by `pocketmine\thread\ThreadSafeLogger`
|
||||
- `AttachableThreadedLogger` is replaced by `pocketmine\thread\AttachableThreadSafeLogger`
|
||||
- `ThreadedLoggerAttachment` is replaced by `pocketmine\thread\ThreadSafeLoggerAttachment`
|
||||
|
||||
## Fixes
|
||||
- Fixed crash on unknown blocks due to late initialization of properties in `UnknownBlock`.
|
||||
|
||||
## API changes
|
||||
### `pocketmine\scheduler`
|
||||
- `AsyncTask->setResult()` now works with thread-safe objects. This was previously not possible due to limitations in the `pthreads` extension.
|
@ -1,791 +0,0 @@
|
||||
# 5.0.0
|
||||
Released 1st June 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.19.80**
|
||||
|
||||
5.0.0 is a major feature update to PocketMine-MP, including support for Bedrock worlds from 1.13 onwards, a large array of new blocks and items, and various changes to the plugin API.
|
||||
|
||||
It is **not** compatible with plugins written for 4.x.y, and plugins may require code changes to work with it.
|
||||
|
||||
**As this changelog is quite large, its accuracy and completeness cannot be guaranteed.**
|
||||
Make sure you're looking at the [latest revision](https://github.com/pmmp/PocketMine-MP/blob/stable/changelogs/5.0.md), as it may be amended after release.
|
||||
|
||||
## Core
|
||||
- Worlds are now saved according to the Bedrock 1.19.80 format.
|
||||
- Worlds generated by Bedrock from 1.13.0 and up are now supported (previously, only worlds up to 1.12 were supported).
|
||||
- `/particle` now accepts strings for particle data instead of integers.
|
||||
- `/particle` no longer accepts integers for block or item IDs.
|
||||
- The usage of `blockcrack`, `iconcrack` and `blockdust` particle types in `/particle` now follows the same pattern as
|
||||
other particle types, with the data for each being passed in the `data` parameter instead of being baked into the
|
||||
particle name.
|
||||
- Commands are now enabled by default in worlds exported from PocketMine-MP to Bedrock.
|
||||
|
||||
## Build system
|
||||
- `build/generate-block-serializer-consts.php` has been added to generate `BlockTypeNames`, `BlockStateNames` and `BlockStateStringValues` in the `pocketmine\data\bedrock\block` package.
|
||||
- `build/generate-item-type-names.php` has been added to generate `ItemTypeNames` in the `pocketmine\data\bedrock\item` package.
|
||||
- `build/generate-runtime-enum-serializers.php` has been added to generate `RuntimeEnumSerializer`, `RuntimeEnumSerializerTrait`, and `RuntimeEnumSizeCalculatorTrait` in `pocketmine\data\runtime` package.
|
||||
|
||||
## Localization
|
||||
- Localized disconnect messages are now used in the following cases:
|
||||
- Server full
|
||||
- Player not on the server whitelist
|
||||
- Player on the server ban list
|
||||
- Invalid skin
|
||||
- Invalid username
|
||||
- Kicked using `/kick`
|
||||
- Banned using `/ban`
|
||||
- Failure to find a safe spawn position
|
||||
- Session open, session close and session player name discovery messages are now localized.
|
||||
- All permissions now have localized descriptions. These are not currently used by PocketMine-MP, but may be useful for plugins.
|
||||
|
||||
## Performance
|
||||
- Improved performance of dropping block inventory contents when the block is destroyed.
|
||||
- Improved light propagation performance by 10-15%.
|
||||
- [`ext-pmmpthread` version 6.0.0](https://github.com/pmmp/ext-pmmpthread/releases/tag/6.0.0) is now used, featuring significant performance improvements for thread-safe objects and various threading use-cases.
|
||||
|
||||
## Tools
|
||||
- The following tool scripts have been added:
|
||||
- `generate-block-palette-spec.php` - generates a JSON file with a readable overview of blocks, their state
|
||||
properties, and their possible values
|
||||
- `generate-blockstate-upgrade-schema.php` - generates JSON blockstate upgrade schemas like those found
|
||||
in [BedrockBlockUpgradeSchema](https://github.com/pmmp/BedrockBlockUpgradeSchema)
|
||||
- `generate-item-upgrade-schema.php` - generates JSON item ID/meta upgrade schemas like those found
|
||||
in [BedrockItemUpgradeSchema](https://github.com/pmmp/BedrockItemUpgradeSchema)
|
||||
- `generate-bedrock-data-from-packets.php` - generates various files for [BedrockData](https://github.com/pmmp/BedrockData)
|
||||
- This script accepts a txt file containing base64-encoded packet dumps.
|
||||
- This script has been in use for several years, but has only now been open-sourced.
|
||||
- It's used to generate data such as crafting recipes, creative inventory data, and various other blobs of data needed to support the current version of Minecraft: Bedrock Edition.
|
||||
|
||||
## Gameplay
|
||||
### Blocks
|
||||
- Added the following new blocks:
|
||||
- Amethyst Block
|
||||
- Ancient Debris
|
||||
- Azalea Leaves
|
||||
- Basalt
|
||||
- Blackstone blocks, slabs, stairs, and walls
|
||||
- Cakes with Candle & Dyed Candle
|
||||
- Calcite
|
||||
- Candle & Dyed Candle
|
||||
- Cartography Table (not currently usable due to maps not being implemented)
|
||||
- Cauldron
|
||||
- Cave Vines
|
||||
- Chain
|
||||
- Chiseled Deepslate
|
||||
- Chiseled Nether Bricks
|
||||
- Chiseled Polished Blackstone
|
||||
- Chorus Flower
|
||||
- Chorus Plant
|
||||
- Cobbled Deepslate blocks, slabs, stairs, and walls
|
||||
- Copper Ore
|
||||
- Copper block (random oxidation not yet implemented)
|
||||
- Crached Deepslate Tiles
|
||||
- Cracked Deepslate Bricks
|
||||
- Cracked Nether Bricks
|
||||
- Cracked Polished Blackstone Bricks
|
||||
- Crimson buttons, doors, fences, fence gates, hyphae, planks, pressure plates, signs, slabs, stairs, stems, and trapdoors
|
||||
- Crying Obsidian
|
||||
- Cut Copper block, stairs and slabs (random oxidation not yet implemented)
|
||||
- Deepslate
|
||||
- Deepslate Bricks blocks, slabs, stairs, and walls
|
||||
- Deepslate Ores (coal, copper, diamond, emerald, gold, iron, lapis lazuli, redstone)
|
||||
- Deepslate Tiles blocks, slabs, stairs, and walls
|
||||
- Flowering Azalea Leaves
|
||||
- Froglight (pearlescent, verdant, ochre)
|
||||
- Gilded Blackstone
|
||||
- Glow Item Frame
|
||||
- Hanging Roots
|
||||
- Honeycomb Block
|
||||
- Light Block
|
||||
- Lightning Rod
|
||||
- Mangrove Leaves
|
||||
- Mangrove Roots
|
||||
- Mangrove buttons, doors, fences, fence gates, logs, planks, pressure plates, signs, slabs, stairs, trapdoors, and wood
|
||||
- Mud Bricks blocks, slabs, stairs, and walls
|
||||
- Muddy Mangrove Roots
|
||||
- Nether Gold Ore
|
||||
- Netherite Block
|
||||
- Polished Basalt
|
||||
- Polished Blackstone Bricks blocks, slabs, stairs, and walls
|
||||
- Polished Blackstone blocks, buttons, pressure plates, slabs, stairs, and walls
|
||||
- Polished Deepslate blocks, slabs, stairs, and walls
|
||||
- Quartz Bricks
|
||||
- Reinforced Deepslate
|
||||
- Rooted Dirt
|
||||
- Sculk
|
||||
- Shroomlight
|
||||
- Smithing Table
|
||||
- Smooth Basalt
|
||||
- Soul Fire
|
||||
- Soul Lantern
|
||||
- Soul Soil
|
||||
- Soul Torch
|
||||
- Spore Blossom
|
||||
- Tinted Glass
|
||||
- Tuff
|
||||
- Twisting Vines
|
||||
- Warped Wart Block
|
||||
- Warped buttons, doors, fences, fence gates, hyphae, planks, pressure plates, signs, slabs, stairs, stems, and trapdoors
|
||||
- Weeping Vines
|
||||
- Wither Rose
|
||||
- Added support for basalt generators
|
||||
- Added support for dyeing sign text and making it glow.
|
||||
- All-sided logs ("wood", for want of a better name) can now be placed in X, Y, and Z orientations.
|
||||
- Coral and coral fans now behave correctly when placed out of water (they no longer immediately die).
|
||||
- Fixed dead bush being able to be placed on some invalid blocks (e.g. stone).
|
||||
- Fixed lava setting entities on fire for an incorrect duration (Java vs Bedrock inconsistency).
|
||||
- Fixed sugarcane not being able to be placed on some blocks.
|
||||
- Iron Ore and Gold Ore now drop Raw Iron and Raw Gold respectively, instead of the ore blocks.
|
||||
- Item frames can now be placed on the top and bottom of blocks.
|
||||
- Stripping logs by right-clicking them with an axe is now supported.
|
||||
- TNT can now be ignited by fire charges.
|
||||
- Vines can now only be placed on the side of full-cube blocks.
|
||||
- Walls now connect when placed, following the pre-1.16 logic. (1.16 logic is planned to be implemented, but currently low priority.)
|
||||
- Anvils are now damaged when they hit the ground after falling.
|
||||
- Added missing sounds for anvils hitting the ground after falling.
|
||||
- Anvils now damage entities when they fall on top of them.
|
||||
|
||||
### Items
|
||||
- Added the following new items:
|
||||
- Amethyst Shard
|
||||
- Antidote (from Education Edition)
|
||||
- Copper Ingot
|
||||
- Disc Fragment (5)
|
||||
- Echo Shard
|
||||
- Elixir (from Education Edition)
|
||||
- Eye Drops (from Education Edition)
|
||||
- Fire Charge
|
||||
- Glow Berries
|
||||
- Glow Ink Sac
|
||||
- Honey Bottle
|
||||
- Honeycomb
|
||||
- Mangrove Boat (incomplete)
|
||||
- Music Disc (5)
|
||||
- Music Disc (Otherside)
|
||||
- Music Disc (Pigstep)
|
||||
- Netherite Axe
|
||||
- Netherite Boots
|
||||
- Netherite Chestplate
|
||||
- Netherite Helmet
|
||||
- Netherite Ingot
|
||||
- Netherite Leggings
|
||||
- Netherite Pickaxe
|
||||
- Netherite Scrap
|
||||
- Netherite Shovel
|
||||
- Netherite Sword
|
||||
- Phantom Membrane
|
||||
- Raw Copper
|
||||
- Raw Gold
|
||||
- Raw Iron
|
||||
- Spyglass
|
||||
- Suspicious Stew
|
||||
- Tonic (from Education Edition)
|
||||
- Glass bottles can now be filled with water by clicking on a water source block.
|
||||
- Implemented Swift Sneak enchantment.
|
||||
- Armour durability is now only reduced when the wearer receives a type of damage that the armour can protect against.
|
||||
- Bells now ring when hit by a projectile.
|
||||
|
||||
### Worlds
|
||||
- World height of -64 to 319 is now supported.
|
||||
- Added support for 3D biomes. This isn't used by PocketMine-MP yet, but is necessary to be able to fully load 1.18 worlds.
|
||||
|
||||
## API
|
||||
### General
|
||||
- Union and mixed native parameter, return and property types are now used where appropriate.
|
||||
- Protected and public properties now use native property types wherever possible.
|
||||
- Parameter and return typehints have been applied in many places where it wasn't previously possible.
|
||||
|
||||
### Dependencies
|
||||
- [`ext-pmmpthread` version 6.0.0](https://github.com/pmmp/ext-pmmpthread/releases/6.0.0) (renamed from `ext-pthreads`) is now required. This version features major API changes and improvements. Please read the [upgrading guide](https://github.com/pmmp/ext-pmmpthread/blob/fork/docs/UPGRADING_4.x_to_6.0.md) for details.
|
||||
- [`pocketmine/snooze` version 0.5.0](https://github.com/pmmp/Snooze/releases/0.5.0) is now required.
|
||||
- [`pocketmine/raklib` version 0.15.0](https://github.com/pmmp/RakLib/releases/0.15.0) is now required.
|
||||
- [`pocketmine/raklib-ipc` version 0.2.0](https://github.com/pmmp/RakLibIpc/releases/0.2.0) is now required.
|
||||
- `pocketmine/classloader` and `pocketmine/log-pthreads` packages have been removed. The relevant classes from these packages are now included in-house in the `pocketmine/thread` namespace.
|
||||
- `BaseClassLoader` is replaced with `pocketmine\thread\ThreadSafeClassLoader`
|
||||
- `ThreadedLogger` is replaced by `pocketmine\thread\ThreadSafeLogger`
|
||||
- `AttachableThreadedLogger` is replaced by `pocketmine\thread\AttachableThreadSafeLogger`
|
||||
- `ThreadedLoggerAttachment` is replaced by `pocketmine\thread\ThreadSafeLoggerAttachment`
|
||||
- `webmozart/path-util` has been removed (replaced by [`symfony/filesystem`](https://github.com/symfony/filesystem)).
|
||||
|
||||
### `pocketmine\block`
|
||||
#### Highlights
|
||||
- Blocks no longer use internal Minecraft IDs and metadata to identify themselves. All APIs associated with legacy IDs
|
||||
and meta have been removed.
|
||||
- A new set of runtime IDs generated from `VanillaBlocks` is used to identify block types. These IDs are defined
|
||||
in `BlockTypeIds`.
|
||||
- These new IDs are used for runtime representation of blocks on chunks, and for type comparison purposes.
|
||||
- Block type IDs are used at **runtime only**. **Do not store them in configs or databases**, as they are subject to
|
||||
change without warning.
|
||||
- Block type IDs are **specific to PocketMine-MP** and have no relation to the IDs used by Minecraft.
|
||||
- Block type IDs cannot be negative
|
||||
- Block type IDs must not be reused, even if overriding an already defined block
|
||||
- Block state properties (e.g. facing, colour, etc.) are now represented by PM-specific state data instead of legacy
|
||||
metadata. The state data consists of:
|
||||
- Block-item state properties - retained by items when the block is broken (colour, wet/dry, coral type, etc.) - handled by `Block->describeBlockItemState()`
|
||||
- Block-only state data - discarded when the block is broken (facing direction, lit/unlit, powered/unpowered, etc.) - handled by `Block->describeBlockOnlyState()`
|
||||
- Chunks now store dynamic state ID derived from the runtime type ID and runtime (PocketMine-MP defined) state data.
|
||||
- Introduced "type tags" concept, which allows marking certain blocks as having certain behaviours.
|
||||
- The idea for this system was borrowed from the Minecraft Java tags system.
|
||||
- It's still in very early concept stage, but is currently used for deciding which types of blocks plants can be placed on without needing to enumerate every single ID in every class, eliminating a bunch of boilerplate code and improving consistency.
|
||||
- All `Block` descendents now accept `BlockTypeInfo` in the constructor, instead of `BlockBreakInfo`. This allows for future additions without needing to change dozens of overridden constructors.
|
||||
- `&$returnedItems` reference parameter is now used in some places such as `Block->onInteract()` to enable actions to return items to players without caring about whether they are in creative or anything else.
|
||||
- This eliminates boilerplate code of deciding whether to set the player's held item or not, as well as automatically dropping any overflow items that don't fit into the inventory.
|
||||
- This is currently used when filling/emptying cauldrons using buckets or glass bottles.
|
||||
- Dependency between `RuntimeBlockStateRegistry` (previously `BlockFactory`) and `VanillaBlocks` has been inverted.
|
||||
- Now, blocks types are defined in `VanillaBlocks`
|
||||
- `RuntimeBlockStateRegistry` automatically registers states for blocks defined in `VanillaBlocks`.
|
||||
- Manual registration in `RuntimeBlockStateRegistry` is still required for custom blocks (see section below about registering new blocks).
|
||||
- `RuntimeBlockStateRegistry` now has only one purpose - to map internal blockstate IDs to `Block` objects when reading blocks from chunks. It should not be used by plugins unless registering new blocks.
|
||||
- To get a block at runtime, e.g. stone, use `VanillaBlocks::STONE()`
|
||||
- To load a block from **old** config or database data:
|
||||
1. Use `GlobalBlockStateHandlers::getUpgrader()->upgradeIntIdMeta()` to convert it to modern data
|
||||
2. Pass the data to `GlobalBlockStateHandlers::getDeserializer()` to get a blockstate ID
|
||||
3. Pass the blockstate ID to `RuntimeBlockStateRegistry::fromStateId()` to get a `Block` instance
|
||||
- Prefer using `StringToItemParser` wherever possible for configs and databases (see `lookupAliases()` and `lookupBlockAliases()`).
|
||||
|
||||
#### Registering new blocks
|
||||
##### In a plugin
|
||||
To add a vanilla block in a plugin which isn't yet supported by PocketMine-MP, do the following:
|
||||
|
||||
1. Get a new type ID using `BlockTypeIds::newId()` - _you'll want to keep this in a property somewhere if you want to
|
||||
compare using `getTypeId()` later_
|
||||
2. Set up the block type somewhere - _this can be anywhere you like, e.g. a plugin main class property, but using
|
||||
a `RegistryTrait` class is recommended - you'll need this later to create new instances of the block_
|
||||
3. Register the block in `RuntimeBlockStateRegistry` - _this informs the server of all the block's possible states so
|
||||
that it can be read from chunks at runtime_
|
||||
4. Register a deserializer for the block's Minecraft ID in `BlockStateToObjectDeserializer` - _needed for the block to
|
||||
be recognized when loaded from disk_
|
||||
5. Register a serializer for the block in `BlockObjectToStateSerializer` - _needed for the block to be saved to disk,
|
||||
and to be sent over the network_
|
||||
6. Optionally, register a string alias for the block in `StringToItemParser` - _so that it can be given via `/give`_
|
||||
|
||||
To see a demo of how to do this in a plugin, see [this example plugin](https://github.com/pmmp/RegisterBlocksDemoPM5).
|
||||
|
||||
Registering custom blocks follows a similar process, but requires additional steps to modify `BlockStateDictionary`
|
||||
which won't be covered here.
|
||||
Since this is not currently officially supported by PocketMine-MP, this won't be covered here.
|
||||
|
||||
This is admittedly rather more of a hassle than in PM4, but this system offers significantly more flexibility than the
|
||||
old system.
|
||||
|
||||
##### As a PocketMine-MP core contribution
|
||||
To register a new vanilla block into the core, the process is slightly different:
|
||||
|
||||
1. Instead of using `BlockTypeIds::newId()`, add a new constant for the block to `BlockTypeIds`
|
||||
2. Register the new block in `VanillaBlocks` - `RuntimeBlockStateRegistry` will automagically take notice of all blocks
|
||||
defined in `VanillaBlocks`
|
||||
3. Follow steps 4 onwards above
|
||||
|
||||
#### Change list
|
||||
- The following classes have been removed:
|
||||
- `BlockIdentifierFlattened`
|
||||
- `BlockLegacyIdHelper`
|
||||
- `BlockLegacyIds`
|
||||
- `BlockLegacyMetadata`
|
||||
- `utils\BlockDataSerializer`
|
||||
- `utils\ColorInMetadataTrait` - `utils\ColoredTrait` now implements colour type data serialization uniformly
|
||||
- `utils\InvalidBlockStateException` - this has been superseded by `pocketmine\data\runtime\InvalidSerializedRuntimeDataException`
|
||||
- `utils\NormalHorizontalFacingInMetadataTrait` - `utils\HorizontalFacingTrait` now implements facing type data serialization uniformly
|
||||
- `utils\PillarRotationInMetadataTrait` - `utils\PillarRotationTrait` now implements rotation type data serialization uniformly
|
||||
- The following classes have been renamed:
|
||||
- `BlockFactory` -> `RuntimeBlockStateRegistry` - this class is now exclusively used for mapping state IDs to block instances for runtime chunk block reading
|
||||
- `Skull` -> `MobHead`
|
||||
- `utils\SkullType` -> `utils\MobHeadType`
|
||||
- `utils\TreeType` -> `pocketmine\world\generator\object\TreeType`
|
||||
- The following classes have been added:
|
||||
- `BaseCake`
|
||||
- `BaseFire`
|
||||
- `BlockTypeIds` - list of type IDs, one for each entry in `VanillaBlocks`
|
||||
- `BlockTypeInfo`
|
||||
- `BlockTypeTags`
|
||||
- `CakeWithCandle`
|
||||
- `CakeWithDyedCandle`
|
||||
- `Candle`
|
||||
- `CartographyTable`
|
||||
- `Chain`
|
||||
- `CopperOre`
|
||||
- `CopperSlab`
|
||||
- `CopperStairs`
|
||||
- `Copper`
|
||||
- `DyedCandle`
|
||||
- `GildedBlackstone`
|
||||
- `GoldOre`
|
||||
- `HangingRoots`
|
||||
- `IronOre`
|
||||
- `Light`
|
||||
- `LightningRod`
|
||||
- `NetherGoldOre`
|
||||
- `Sculk`
|
||||
- `SmithingTable`
|
||||
- `SoulFire`
|
||||
- `WitherRose`
|
||||
- `utils\CandleTrait`
|
||||
- `utils\CopperOxidation`
|
||||
- `utils\CopperTrait`
|
||||
- `utils\SaplingType` - enum of all sapling types
|
||||
- `utils\WallConnectionType` - enum of all possible wall connection types
|
||||
- `utils\WoodTypeTrait`
|
||||
- `utils\WoodType` - enum of all possible wood types, used for wood material blocks like planks and logs
|
||||
- The following API methods have been removed:
|
||||
- `Block->getId()` - for type comparisons, use `Block->getTypeId()` instead
|
||||
- `Block->getMeta()` - for state comparisons, use `Block->getStateId()` instead
|
||||
- `Block->getStateBitmask()`
|
||||
- `Block->readStateFromData()`
|
||||
- `Block->writeStateToItemMeta()`
|
||||
- `Block->writeStateToMeta()`
|
||||
- `BlockFactory->get()` - see notes above about `RuntimeBlockStateRegistry`
|
||||
- `BlockIdentifier->getAllBlockIds()`
|
||||
- `BlockIdentifier->getBlockId()`
|
||||
- `BlockIdentifier->getItemId()`
|
||||
- `BlockIdentifier->getVariant()`
|
||||
- `Door->isPowered()`
|
||||
- `Door->setPowered()`
|
||||
- `MobHead->isNoDrops()` (previously `Skull->isNoDrops()`)
|
||||
- `MobHead->setNoDrops()` (previously `Skull->setNoDrops()`)
|
||||
- `VanillaBlocks::*_GLAZED_TERRACOTTA()` - use `VanillaBlocks::GLAZED_TERRACOTTA()->setColor(DyeColor::WHATEVER())` instead
|
||||
- `utils\FallableTrait->getId()` is no longer required
|
||||
- `utils\FallableTrait->getMeta()` is no longer required
|
||||
- `utils\MobHeadType->getMagicNumber()` (previously `utils\SkullType->getMagicNumber()`)
|
||||
- `utils\MobHeadType::fromMagicNumber()` (previously `utils\SkullType::fromMagicNumber()`)
|
||||
- The following constants have been removed:
|
||||
- `Block::INTERNAL_METADATA_BITS`
|
||||
- `Block::INTERNAL_METADATA_MASK`
|
||||
- The following API methods have been renamed:
|
||||
- `Block->getFullId()` -> `Block->getStateId()`
|
||||
- `Block->isSameType()` -> `Block->hasSameTypeId()`
|
||||
- `MobHead->getSkullType()` -> `MobHead->getMobHeadType()` (previously `Skull->getSkullType()`)
|
||||
- `MobHead->setSkullType()` -> `MobHead->setMobHeadType()` (previously `Skull->setSkullType()`)
|
||||
- The following API methods have signature changes:
|
||||
- `Block->onBreak()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Block->onInteract()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Block->readStateFromWorld()` now returns `Block` - this allows blocks to replace themselves with a different block entirely based on world conditions.
|
||||
- `BlockIdentifier->__construct()` now accepts `int $blockTypeId`, and no longer accepts `int $blockId, int $variant, ?int $itemId`
|
||||
- `ItemFrame->getFacing()` may now return `Facing::UP` and `Facing::DOWN`
|
||||
- `ItemFrame->setFacing()` now accepts `Facing::UP` and `Facing::DOWN`
|
||||
- `Leaves->__construct()` now accepts `LeavesType $leavesType` instead of `TreeType $treeType`
|
||||
- `RuntimeBlockStateRegistry->register()` no longer accepts an `$override` parameter.
|
||||
- `Sapling::__construct()` now accepts `SaplingType $saplingType` instead of `TreeType $treeType`
|
||||
- `utils\SignText::__construct()` now accepts two new optional parameters: `?Color $baseColor` and `bool $glowing`
|
||||
- `utils\SignText::fromBlob()` now accepts two new optional parameters: `?Color $baseColor` and `bool $glowing`
|
||||
- The following API methods have been added:
|
||||
- `protected Block->describeBlockOnlyState(RuntimeDataDescriber $w) : void` - describes state properties which are discarded when the block is broken or block-picked, such as facing, powered, etc.
|
||||
- `public Block->describeBlockItemState(RuntimeDataDescriber $w) : void` - describes state properties which are kept by the item when the block is broken or block-picked, such as dye color
|
||||
- `public Block->generateStatePermutations() : \Generator<int, Block, void, void>` - yields all possible states this block type can be in (used for `RuntimeBlockStateRegistry`)
|
||||
- `public Block->getTypeTags() : array<string>`
|
||||
- `public Block->hasTypeTag(string $tag) : bool`
|
||||
- `public Block->isFireProofAsItem() : bool`
|
||||
- `public Block->onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void`
|
||||
- `public BlockIdentifier->getBlockTypeId() : int` - returns the block's type ID according to `BlockTypeIds`
|
||||
- `public Furnace->getFurnaceType() : utils\FurnaceType`
|
||||
- `public GlazedTerracotta->getColor() : utils\DyeColor` (from `ColoredTrait`) - this was previously unsupported due to legacy limitations
|
||||
- `public GlazedTerracotta->setColor(utils\DyeColor $color) : $this` (from `ColoredTrait`) - this was previously unsupported due to legacy limitations
|
||||
- `public Leaves->getLeavesType() : utils\LeavesType` - returns the type of leaves
|
||||
- `public Wall->getConnection(int $face) : utils\WallConnectionType`
|
||||
- `public Wall->getConnections() : array<int, utils\WallConnectionType>` - returns the wall's connections and their types (see `utils\WallConnectionType`)
|
||||
- `public Wall->isPost() : bool`
|
||||
- `public Wall->setConnection(int $face, ?utils\WallConnectionType $type) : $this`
|
||||
- `public Wall->setConnections()` - sets the wall's connections and their types (see `utils\WallConnectionType`)
|
||||
- `public Wall->setPost(bool $post) : $this`
|
||||
- `public Wood->isStripped() : bool`
|
||||
- `public Wood->setStripped(bool $stripped) : $this`
|
||||
- `public static BlockBreakInfo::axe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : BlockBreakInfo`
|
||||
- `public static BlockBreakInfo::pickaxe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : BlockBreakInfo`
|
||||
- `public static BlockBreakInfo::shovel(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : BlockBreakInfo`
|
||||
- `public static BlockBreakInfo::tier(float $hardness, int $toolType, ToolTier $toolTier, ?float $blastResistance = null) : BlockBreakInfo`
|
||||
- `public tile\Spawnable->getRenderUpdateBugWorkaroundStateProperties(Block $block) : array<string, Tag>` - allows spawnable tiles to spoof block state properties to work around client-side rendering bugs without actually changing the block server-side
|
||||
- `public utils\SignText->getBaseColor() : \pocketmine\color\Color`
|
||||
- `public utils\SignText->isGlowing() : bool`
|
||||
- The following classes now use new traits, adding API methods and/or properties:
|
||||
- `FenceGate` uses `utils\WoodTypeTrait`
|
||||
- `GlazedTerracotta` uses `utils\ColoredTrait`
|
||||
- `Planks` uses `utils\WoodTypeTrait`
|
||||
- `Wood` uses `utils\WoodTypeTrait`
|
||||
- `WoodenButton` uses `utils\WoodTypeTrait`
|
||||
- `WoodenDoor` uses `utils\WoodTypeTrait`
|
||||
- `WoodenFence` uses `utils\WoodTypeTrait`
|
||||
- `WoodenPressurePlate` uses `utils\WoodTypeTrait`
|
||||
- `WoodenSlab` uses `utils\WoodTypeTrait`
|
||||
- `WoodenStairs` uses `utils\WoodTypeTrait`
|
||||
- `WoodenTrapdoor` uses `utils\WoodTypeTrait`
|
||||
- The following API interface requirements have been added (BC breaking):
|
||||
- `public utils\Fallable->getFallDamagePerBlock() : float` (default implementation provided by `utils\FallableTrait`)
|
||||
- `public utils\Fallable->getLandSound() : ?Sound` (default implementation provided by `utils\FallableTrait`)
|
||||
- `public utils\Fallable->getMaxFallDamage() : float` (default implementation provided by `utils\FallableTrait`)
|
||||
- `public utils\Fallable->onHitGround(FallingBlock $blockEntity) : bool` (default implementation provided by `utils\FallableTrait`)
|
||||
|
||||
### `pocketmine\command`
|
||||
- Command permissions are now always checked by the server when running a command.
|
||||
- This only affects commands implemented by extending `Command`. Plugins using `PluginBase->onCommand()` are not affected by this change, since they already had permissions checked by the server anyway.
|
||||
- Previously, direct inheritors of `Command` were responsible for checking permissions, which required developers to duplicate the same code in every command, and opened lots of potential for security vulnerabilities.
|
||||
- If you want to do something on permission denied (e.g. sending a special message, or audit logging), you can do so by overriding `Command->testPermission()`, instead of baking the code directly into `Command->execute()`.
|
||||
- If you don't want to use permissions at all, just create a permission with a default of `true` (or belonging to `pocketmine.group.user`) and assign that.
|
||||
- `SimpleCommandMap` now requires all commands to have a permission set when registered.
|
||||
- If you actually want to allow everyone to use your command (not advised), you can add a new permission to the `pocketmine.group.user` group, or use `default: true` for `plugin.yml` permissions.
|
||||
- The following API methods have changed behaviour:
|
||||
- `Command->testPermissionSilent()` now returns `false` if there are no permissions associated with the command. This is to prevent commands with no permissions being usable by everyone, which has previously been a source of security issues.
|
||||
- The following API methods have been added:
|
||||
- `public Command->getPermissions() : list<string>` - returns a list of permissions which grant usage access to this command. A user with one or more of these permissions will be able to invoke the command's `execute()` method
|
||||
- `public Command->setPermissions(list<string> $permissions) : void` - sets the permissions which grant usage access to this command. This should be used instead of `setPermission()` with `;` separators (which is now deprecated)
|
||||
|
||||
### `pocketmine\crafting`
|
||||
- JSON models have been updated to reflect updated crafting data format.
|
||||
- The following enum classes have new members:
|
||||
- `ShapelessRecipeType` has new members `CARTOGRAPHY` and `SMITHING`
|
||||
- The following classes have been added:
|
||||
- `ExactRecipeIngredient` - matches an exact item
|
||||
- `MetaWildcardRecipeIngredient` - matches an item with the given legacy Minecraft ID, but any metadata value
|
||||
- `RecipeIngredient` interface
|
||||
- `TagWildcardRecipeIngredient` - matches an item based on its Minecraft tags, e.g. `minecraft:wooden_tier`
|
||||
- The following API methods have signature changes:
|
||||
- `FurnaceRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
|
||||
- `FurnaceRecipe->getInput()` now returns `RecipeIngredient` instead of `Item`
|
||||
- `PotionContainerChangeRecipe->__construct()` now accepts `string, RecipeIngredient, string` (using Minecraft string IDs instead of legacy integers).
|
||||
- `PotionContainerChangeRecipe->getIngredient()` now returns `RecipeIngredient` instead of `Item`.
|
||||
- `PotionContainerChangeRecipe->getInputItemId()` now returns `string` (using Minecraft string IDs instead of legacy integers).
|
||||
- `PotionContainerChangeRecipe->getOutputItemId()` now returns `string` (using Minecraft string IDs instead of legacy integers).
|
||||
- `PotionTypeRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
|
||||
- `PotionTypeRecipe->getIngredient()` now returns `RecipeIngredient` instead of `Item`
|
||||
- `PotionTypeRecipe->getInput()` now returns `RecipeIngredient` instead of `Item`
|
||||
- `ShapedRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
|
||||
- `ShapedRecipe->getIngredient()` now returns `?RecipeIngredient` instead of `?Item`
|
||||
- `ShapedRecipe->getIngredientList()` now returns `RecipeIngredient[]` instead of `Item[]`
|
||||
- `ShapedRecipe->getIngredientMap()` now returns `RecipeIngredient[][]` instead of `Item[][]`
|
||||
- `ShapelessRecipe->__construct()` `$type` parameter is now mandatory.
|
||||
- `ShapelessRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
|
||||
- `ShapelessRecipe->getIngredientList()` now returns `RecipeIngredient[]` instead of `Item[]`
|
||||
|
||||
### `pocketmine\data`
|
||||
- New packages `bedrock\block` and `bedrock\item` have been added. These packages contain all the necessary code for loading and saving Bedrock blocks and items from disk.
|
||||
- New package `runtime` has been added. This package contains code for serializing runtime data for blocks and items.
|
||||
- `LegacyToStringBidirectionalIdMap` has been reduced to `LegacyToStringIdMap`.
|
||||
- Since we never map from string ID to legacy ID, bidirectional mapping is no longer necessary.
|
||||
- This affects the following subclasses:
|
||||
- `LegacyBiomeIdToStringIdMap`
|
||||
- `LegacyBlockIdToStringIdMap`
|
||||
- `LegacyEntityIdToStringIdMap`
|
||||
- `LegacyItemIdToStringIdMap`
|
||||
- The following internal API methods have been added:
|
||||
- `public LegacyToStringIdMap->add(string $string, int $legacy) : void` - adds a mapping from a custom legacy ID to custom string ID, needed for upgrading old saved data
|
||||
|
||||
### `pocketmine\entity`
|
||||
- `Entity` now declares new abstract methods which must be implemented by subclasses:
|
||||
- `public Entity->getInitialDragMultiplier() : float`
|
||||
- `public Entity->getInitialGravity() : float`
|
||||
- The following new API methods have been added:
|
||||
- `public Living->getDisplayName() : string`
|
||||
- The following API methods have changed signatures:
|
||||
- `EntityFactory->register()` no longer accepts a `$legacyMcpeSaveId` parameter (now handled by internal conversions instead).
|
||||
- The following API methods have been renamed:
|
||||
- `Entity->isImmobile()` -> `Entity->hasNoClientPredictions()`
|
||||
- `Entity->setImmobile()` -> `Entity->setNoClientPredictions()`
|
||||
- The following internal fields have been renamed:
|
||||
- `Entity->immobile` -> `Entity->noClientPredictions`
|
||||
- The following classes have been removed:
|
||||
- `EntityLegacyIds`
|
||||
|
||||
### `pocketmine\event`
|
||||
- The following classes have inheritance changes:
|
||||
- `block\BlockPlaceEvent` no longer extends `BlockEvent`, and therefore no longer has `getBlock()`. Use `getTransaction()` instead (may contain multiple blocks).
|
||||
- `BlockFormEvent` now includes information about the block which caused the event.
|
||||
|
||||
- The following new classes have been added:
|
||||
- `world\WorldDisplayNameChangeEvent` - called when a world's display name is changed
|
||||
- The following classes have been renamed:
|
||||
- `entity\ExplosionPrimeEvent` -> `entity\EntityPreExplodeEvent`
|
||||
- The following API methods have been added:
|
||||
- `public block\BlockFormEvent->getCausingBlock() : Block`
|
||||
- `public block\BlockGrowEvent->getPlayer() : ?Player` - returns the player that triggered the block growth, or `null` if it was not triggered by a player
|
||||
- `public block\BlockPlaceEvent->getTransaction() : BlockTransaction` - returns the transaction containing a list of changed block positions and the blockstates they will be changed to
|
||||
- `public server\DataPacketSendEvent->setPackets(list<ClientboundPacket> $packets) : void`
|
||||
- The following API methods have changed signatures:
|
||||
- `block\BlockPlaceEvent->__construct()` now accepts `BlockTransaction $transaction` instead of `Block $blockPlace, Block $blockReplace`
|
||||
- `entity\EntityPreExplodeEvent->__construct()` has the `$force` parameter renamed to `$radius`
|
||||
- `entity\EntityPreExplodeEvent->getForce() : float` -> `entity\EntityPreExplodeEvent->getRadius() : float`
|
||||
- `entity\EntityPreExplodeEvent->setForce(float $force) : void` -> `entity\EntityPreExplodeEvent->setRadius(float $radius) : void`
|
||||
- The following API methods have been removed:
|
||||
- `block\BlockPlaceEvent->getBlockReplaced()` - this information is now provided in the `BlockTransaction` object returned by `BlockPlaceEvent->getTransaction()`
|
||||
- The following new API constants have been added:
|
||||
- `entity\EntityDamageEvent::CAUSE_FALLING_BLOCK`
|
||||
- `entity\EntityDamageEvent::MODIFIER_ARMOR_HELMET`
|
||||
|
||||
### `pocketmine\event\player`
|
||||
- `PlayerPreLoginEvent`, `PlayerDuplicateLoginEvent` and `PlayerKickEvent` now supports setting separate log reasons (disconnect reason) and disconnect screen messages.
|
||||
- The following classes have been removed:
|
||||
- `PlayerCommandPreprocessEvent`
|
||||
- The following API methods have changed signatures:
|
||||
- `PlayerDuplicateLoginEvent->getDisconnectMessage()` now returns `Translatable|string` instead of `string`
|
||||
- `PlayerDuplicateLoginEvent->setDisconnectMessage()` now accepts `Translatable|string` instead of `string`
|
||||
- `PlayerKickEvent->getReason()` now returns `Translatable|string` instead of `string`
|
||||
- `PlayerKickEvent->setReason()` now accepts `Translatable|string` instead of `string`
|
||||
- `PlayerLoginEvent->getKickMessage()` now returns `Translatable|string` instead of `string`
|
||||
- `PlayerLoginEvent->setKickMessage()` now accepts `Translatable|string` instead of `string`
|
||||
- `PlayerPreLoginEvent->getFinalKickMessage()` now returns `Translatable|string` instead of `string`
|
||||
- `PlayerPreLoginEvent->getKickMessage()` now returns `Translatable|string|null` instead of `string|null`
|
||||
- `PlayerPreLoginEvent->setKickFlag()` (previously `setKickReason()`) now accepts `Translatable|string $disconnectReason, Translatable|string|null $disconnectScreenMessage = null` instead of `Translatable|string $message`
|
||||
- `PlayerPreLoginEvent->setKickReason()` now accepts `Translatable|string` for the `$message` parameter instead of `string`
|
||||
- `PlayerQuitEvent->getQuitReason()` now returns `Translatable|string` instead of `string`
|
||||
- The following API methods have been removed:
|
||||
- `PlayerChatEvent->getFormat()` (use `PlayerChatEvent->getChatFormatter()` instead)
|
||||
- `PlayerChatEvent->setFormat()` (use `PlayerChatEvent->setChatFormatter()` instead)
|
||||
- `PlayerDuplicateLoginEvent->getDisconnectMessage()` - replaced by `getDisconnectReason()` and `getDisconnectScreenMessage()`
|
||||
- `PlayerDuplicateLoginEvent->setDisconnectMessage()` - replaced by `setDisconnectReason()` and `setDisconnectScreenMessage()`
|
||||
- `PlayerKickEvent->getReason()` - replaced by `getDisconnectReason()` and `getDisconnectScreenMessage()`
|
||||
- `PlayerKickEvent->setReason()` - replaced by `setDisconnectReason()` and `setDisconnectScreenMessage()`
|
||||
- The following new API methods have been added:
|
||||
- `public PlayerChatEvent->getChatFormatter() : \pocketmine\player\chat\ChatFormatter` - returns the chat formatter to be used for this event
|
||||
- `public PlayerChatEvent->setChatFormatter(\pocketmine\player\chat\ChatFormatter $formatter) : void` - sets the chat formatter to be used for this event
|
||||
- `public PlayerDeathEvent->getDeathScreenMessage() : Translatable|string` - returns the message to be displayed on the death screen
|
||||
- `public PlayerDeathEvent->setDeathScreenMessage(Translatable|string $deathScreenMessage) : void` - sets the message to be displayed on the death screen
|
||||
- `public PlayerDuplicateLoginEvent->getDisconnectReason() : Translatable|string` - returns the reason for the disconnection displayed in the console and server log
|
||||
- `public PlayerDuplicateLoginEvent->getDisconnectScreenMessage() : Translatable|string|null` - returns the message to be displayed on the disconnect screen (the message in `getDisconnectReason()` is used if null is returned)
|
||||
- `public PlayerDuplicateLoginEvent->setDisconnectReason(Translatable|string $disconnectReason) : void` - sets the reason for the disconnection displayed in the console and server log
|
||||
- `public PlayerDuplicateLoginEvent->setDisconnectScreenMessage(Translatable|string|null $disconnectScreenMessage) : void` - sets the message to be displayed on the disconnect screen (the message in `setDisconnectReason()` is used if null is passed)
|
||||
- `public PlayerKickEvent->getDisconnectReason() : Translatable|string` - returns the reason for the disconnection displayed in the console and server log
|
||||
- `public PlayerKickEvent->getDisconnectScreenMessage() : Translatable|string|null` - returns the message to be displayed on the disconnect screen (the message in `getDisconnectReason()` is used if null is returned)
|
||||
- `public PlayerKickEvent->setDisconnectReason(Translatable|string $disconnectReason) : void` - sets the reason for the disconnection displayed in the console and server log
|
||||
- `public PlayerKickEvent->setDisconnectScreenMessage(Translatable|string|null $disconnectScreenMessage) : void` - sets the message to be displayed on the disconnect screen (the message in `setDisconnectReason()` is used if null is passed)
|
||||
- `public PlayerPreLoginEvent->getDisconnectScreenMessage(int $flag) : Translatable|string|null` - returns the message to be displayed on the disconnect screen for the specified kick flag, if set
|
||||
- `public PlayerPreLoginEvent->getFinalDisconnectScreenMessage() : Translatable|string|null` - returns the message to be displayed on the disconnect screen, taking into account the kick flags set
|
||||
- The following classes have inheritance changes:
|
||||
- `PlayerPreLoginEvent` no longer implements `Cancellable`. This caused unexpected behaviour for most plugin devs due to default-ignoring cancelled events, forcing people to usually have to use `@handleCancelled` to handle the event when they wanted to use it.
|
||||
- The following API constants have been renamed:
|
||||
- `PlayerPreLoginEvent::KICK_REASON_BANNED` -> `PlayerPreLoginEvent::KICK_FLAG_BANNED`
|
||||
- `PlayerPreLoginEvent::KICK_REASON_PLUGIN` -> `PlayerPreLoginEvent::KICK_FLAG_PLUGIN`
|
||||
- `PlayerPreLoginEvent::KICK_REASON_PRIORITY` -> `PlayerPreLoginEvent::KICK_FLAG_PRIORITY`
|
||||
- `PlayerPreLoginEvent::KICK_REASON_SERVER_FULL` -> `PlayerPreLoginEvent::KICK_FLAG_SERVER_FULL`
|
||||
- `PlayerPreLoginEvent::KICK_REASON_SERVER_WHITELISTED` -> `PlayerPreLoginEvent::KICK_FLAG_SERVER_WHITELISTED`
|
||||
- The following API methods have been renamed:
|
||||
- `PlayerPreLoginEvent->clearAllKickReasons()` -> `PlayerPreLoginEvent->clearAllKickFlags()`
|
||||
- `PlayerPreLoginEvent->clearKickReason()` -> `PlayerPreLoginEvent->clearKickFlag()`
|
||||
- `PlayerPreLoginEvent->getFinalKickMessage()` -> `PlayerPreLoginEvent->getFinalDisconnectReason()` (now used for logs only, if a disconnect screen message is set for the highest priority flag)
|
||||
- `PlayerPreLoginEvent->getKickMessage()` -> `PlayerPreLoginEvent->getDisconnectReason()` (now used for logs only, if a disconnect screen message is set for the flag)
|
||||
- `PlayerPreLoginEvent->getKickReasons()` -> `PlayerPreLoginEvent->getKickFlags()`
|
||||
- `PlayerPreLoginEvent->isKickReasonSet()` -> `PlayerPreLoginEvent->isKickFlagSet()`
|
||||
- `PlayerPreLoginEvent->setKickReason()` -> `PlayerPreLoginEvent->setKickFlag()`
|
||||
|
||||
### `pocketmine\item`
|
||||
#### Highlights
|
||||
- `ItemFactory` has been removed. Vanilla item registration is now done via `VanillaItems`.
|
||||
- To get an item at runtime, e.g. iron ingot, use `VanillaItems::IRON_INGOT()`
|
||||
- To get a block as an item, e.g. stone, use `VanillaBlocks::STONE()->asItem()`
|
||||
- To load an item from legacy ID and meta:
|
||||
1. Use `GlobalItemDataHandlers::getUpgrader()->upgradeItemTypeDataInt()` to convert the legacy ID and meta to `SavedItemStackData`
|
||||
2. Pass the itemstack data to `GlobalItemDataHandlers::getDeserializer()` to get an `Item` instance
|
||||
- Items no longer use internal Minecraft string IDs and metadata to identify themselves. All APIs associated with legacy
|
||||
IDs and/or meta have been removed.
|
||||
- A new set of runtime item IDs generated from `VanillaItems` is now used to identify item types. These IDs are defined
|
||||
in `ItemTypeIds`.
|
||||
- These new IDs are primarily intended for type comparison purposes.
|
||||
- Item type IDs are used at **runtime only**. They should **NOT** be stored in configs or databases, as they are not
|
||||
guaranteed to remain the same between versions.
|
||||
- In some cases, items may have additional "type data" which provides extra type information about an item. This
|
||||
replaces item metadata in some cases.
|
||||
- Type data may be used to store dynamic type information such as dye colour, potion type, etc.
|
||||
- Items must have the same type ID **and** type data in order to be stackable.
|
||||
- Blocks, when represented as items:
|
||||
- retain their block type data, but not state data (for example, different colours of concrete don't stack, but things
|
||||
like facing don't affect stackability)
|
||||
- use the negative of their block type ID (e.g. a block with type ID `1` will have an item type ID of `-1`).
|
||||
- Durable items (e.g. tools, armour) now use NBT `Damage` tag to store durability (like Minecraft 1.13+), instead of
|
||||
legacy meta values.
|
||||
- `&$returnedItems` reference parameter is now used in some places (e.g. `onInteractBlock()`) to enable actions to return items to players without caring about whether they are in creative or anything else.
|
||||
- This eliminates boilerplate code of deciding whether to set the player's held item or not, as well as automatically dropping any overflow items that don't fit into the inventory.
|
||||
- This is used for things like filling/emptying buckets and bottles, and equipping armor.
|
||||
- Blocks which previously had separate items, such as mob heads and beds, no longer do. Their item form can be acquired using `Block->asItem()` in the same way as every other block. This is facilitated by the new serializer system.
|
||||
|
||||
#### Implementing new items
|
||||
##### In a plugin
|
||||
This follows a similar process to registering blocks.
|
||||
|
||||
1. Get a new type ID using `ItemTypeIds::newId()` - _you'll want to keep this in a property somewhere if you want to
|
||||
compare using `getTypeId()` later_
|
||||
2. Set up the item type somewhere - _this can be anywhere you like, e.g. a plugin main class property, but using
|
||||
a `RegistryTrait` class is recommended - you'll need this later to create new instances of the item_
|
||||
3. Register a deserializer in `ItemDeserializer` - _needed for the item to be recognized when loaded from disk_
|
||||
4. Register a serializer in `ItemSerializer` - _needed for the item to be saved to disk, and to be sent over the
|
||||
network_
|
||||
5. Optionally, register a string alias for the item in `StringToItemParser` - _so that it can be given via `/give`_
|
||||
|
||||
To see a demo of how to do this in a plugin, see [this example plugin](https://github.com/pmmp/RegisterBlocksDemoPM5).
|
||||
|
||||
Again, it's acknowledged this is rather more cumbersome than it should be, but this is an ongoing process.
|
||||
|
||||
##### As a PocketMine-MP core contribution
|
||||
|
||||
To register a new vanilla item into the core, the process is slightly different:
|
||||
|
||||
1. Instead of using `ItemTypeIds::newId()`, add a new constant for the block to `ItemTypeIds`
|
||||
2. Register the new item in `VanillaItems`
|
||||
3. Follow steps 3 onwards from the plugin instructions above
|
||||
|
||||
#### Change list
|
||||
- `Item` is no longer `json_encode()`-able.
|
||||
- The original purpose of this was to allow items to be serialized to JSON for crafting data generated from `CraftingDataPacket`. Due to changes in the generation methodology, bypassing `Item`s entirely, this is no longer necessary.
|
||||
- In addition, `jsonSerialize()` required the item to know about the method by which it will be serialized (since there is no way to inject context), creating a cyclic dependency between the `Item` implementation and its serialization method.
|
||||
- It's relatively easy to write a replacement method to encode items to JSON as you desire.
|
||||
- `Item::legacyJsonDeserialize()` (previously `Item::jsonDeserialize()`) is retained to allow loading legacy data, although it may be removed in the future.
|
||||
- The following classes have been removed:
|
||||
- `Bed`
|
||||
- `ItemFactory`
|
||||
- `ItemIds`
|
||||
- `Skull`
|
||||
- The following classes have been added:
|
||||
- `BoatType` - enum of all boat types
|
||||
- `CoralFan`
|
||||
- `HoneyBottle`
|
||||
- `MedicineType`
|
||||
- `Medicine`
|
||||
- `Spyglass`
|
||||
- `SuspiciousStewType`
|
||||
- `SuspiciousStew`
|
||||
- The following API methods have been added:
|
||||
- `protected Item->describeState(RuntimeDataDescriber $w) : void`
|
||||
- `public Armor->clearCustomColor() : $this` - clears the custom color of an armor item
|
||||
- `public ArmorTypeInfo->getToughness() : int`
|
||||
- `public ArmorTypeInfo->isFireProof() : bool`
|
||||
- `public Boat->getType() : BoatType`
|
||||
- `public Dye->setColor(\pocketmine\block\utils\DyeColor $color) : $this`
|
||||
- `public Item->getStateId() : int` - returns a runtime numeric state ID for comparisons including information such as coral type, dye color, etc. - DO NOT save this to disk or databases
|
||||
- `public Item->getTypeId() : int` - returns a runtime numeric type ID for comparisons - DO NOT save this to disk or databases
|
||||
- `public Item->isFireProof() : bool`
|
||||
- `public ItemIdentifer->getTypeId() : int`
|
||||
- `public Potion->setType(PotionType $type) : $this`
|
||||
- `public SplashPotion->setType(PotionType $type) : $this`
|
||||
- `public StringToItemParser->lookupAliases(Item $item) : list<string>` - returns a list of all registered aliases for the given item
|
||||
- `public StringToItemParser->lookupBlockAliases(Block $block) : list<string>` - returns a list of all registered aliases for the given block
|
||||
- `public static ItemIdentifier::fromBlock(Block $block) : self`
|
||||
- The following API methods have been removed:
|
||||
- `Boat->getWoodType()`
|
||||
- `Item->getId()` - for type comparisons, use `Item->getTypeId()` instead
|
||||
- `Item->getMeta()` - use the item's specific API methods to compare information such as colour, potion type etc.
|
||||
- `Item->hasAnyDamageValue()` - for meta wildcard recipe ingredients, use `pocketmine\crafting\MetaWildcardRecipeIngredient` instead
|
||||
- `ItemIdentifier->getId()`
|
||||
- `ItemIdentifier->getMeta()`
|
||||
- The following API methods have been renamed:
|
||||
- `Item::jsonDeserialize()` -> `Item::legacyJsonDeserialize()`
|
||||
- The following API methods have signature changes:
|
||||
- `ArmorTypeInfo->__construct()` now accepts optional parameters `int $toughness` and `bool $fireProof`
|
||||
- `BoatType::__construct()` now accepts `BoatType $boatType` instead of `TreeType $woodType`.
|
||||
- `Item->onAttackEntity()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Item->onClickAir()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Item->onDestroyBlock()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Item->onInteractBlock()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `Item->onReleaseUsing()` now accepts `array<Item> &$returnedItems` reference parameter.
|
||||
- `ItemIdentifier->__construct()` no longer accepts a `$variant` parameter, and now expects an item type ID for the ID parameter
|
||||
- `LegacyStringToItemParser->addMapping()` now accepts a string for ID, instead of an integer
|
||||
- The following API methods have behaviour changes:
|
||||
- `Item->equals()`'s `$checkDamage` parameter is now ignored, as tool damage is now stored as an NBT tag. This parameter wasn't removed due to being followed by a second `bool` parameter, which would potentially end up in the wrong place and silently cause bugs in updated plugins.
|
||||
- `Item->equals()`'s `$checkTags` parameter will now cause tool and armor damage to be checked if true.
|
||||
- The following enums have new members:
|
||||
- `ToolTier` has new member `NETHERITE`
|
||||
|
||||
### `pocketmine\network`
|
||||
- The following API methods have changed signatures:
|
||||
- `NetworkSessionManager->close()` now accepts an additional `Translatable|string|null $disconnectScreenMessage` parameter.
|
||||
- The following API methods have changed signatures:
|
||||
- `query\QueryInfo->getPlayerList()` now returns `list<string>` instead of `list<Player>`
|
||||
- `query\QueryInfo->setPlayerList()` now accepts `list<string>` instead of `list<Player>`
|
||||
|
||||
### `pocketmine\player`
|
||||
- The following API methods have changed signatures:
|
||||
- `Player->disconnect()` now accepts `Translatable|string` for `$reason` instead of `string` (to allow localized disconnect messages)
|
||||
- `Player->disconnect()` now accepts an additional `Translatable|string|null $disconnectScreenMessage` parameter, which is the message to be displayed on the disconnect screen (the message in `$reason` is used if null is passed)
|
||||
- `Player->kick()` now accepts `Translatable|string` for `$reason` instead of `string` (to allow localized kick messages)
|
||||
- `Player->kick()` now accepts an additional `Translatable|string|null $disconnectScreenMessage` parameter, which is the message to be displayed on the disconnect screen (the message in `$reason` is used if null is passed)
|
||||
- `Player->sendJukeboxPopup()` now accepts `Translatable|string` instead of `string, string[]`
|
||||
- The following classes have been removed:
|
||||
- `PlayerChunkLoader` - deprecated in 4.19.0 (this was technically internal, but never marked as such)
|
||||
|
||||
### `pocketmine\player\chat`
|
||||
- The following new classes have been added:
|
||||
- `ChatFormatter` - interface implemented by chat formatters - this is far more powerful than the old API
|
||||
- `LegacyRawChatFormatter` - implements the same behaviour previously used by `PlayerChatEvent->setFormat()`
|
||||
- `StandardChatFormatter` - formats chat messages in the vanilla Minecraft style
|
||||
|
||||
### `pocketmine\scheduler`
|
||||
- `AsyncTask->setResult()` now works with thread-safe objects. This was previously not possible due to limitations in the `pthreads` extension.
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following API methods have been added:
|
||||
- `public World->setDisplayName(string $name) : void`
|
||||
- The following API methods have changed signatures:
|
||||
- `Explosion->__construct()` has the `$size` parameter renamed to `$radius`
|
||||
- The following public properties have been renamed:
|
||||
- `Explosion->size` -> `Explosion->radius`
|
||||
|
||||
### `pocketmine\world\format`
|
||||
- Chunks are now considered dirty (modified) by default, unless loaded from a `WorldProvider` by `World`. Previously, chunks were considered unmodified by default, which allowed several pathways to bugs.
|
||||
- The following classes have been added:
|
||||
- `io\GlobalBlockStateHandlers` - gives access to block data serializer, deserializer, and upgraders
|
||||
- `io\GlobalItemDataHandlers` - gives access to item data serializer, deserializer, and upgraders
|
||||
- `io\LoadedChunkData` - represents a chunk loaded from disk, along with information such as whether the chunk was upgraded and what fixes it requires
|
||||
- The following new API methods have been added:
|
||||
- `public SubChunk->getBiomeArray() : PalettedBlockArray`
|
||||
- The following classes have been removed:
|
||||
- `BiomeArray` - `PalettedBlockArray` is now used for 3D biome data
|
||||
- The following API methods have changed signatures:
|
||||
- `Chunk->getBiomeId()` now accepts `int $x, int $y, int $z` instead of `int $x, int $z`
|
||||
- `Chunk->setBiomeId()` now accepts `int $x, int $y, int $z` instead of `int $x, int $z`
|
||||
- `Chunk->__construct()` no longer accepts `BiomeArray` as a parameter (contained in each subchunk instead)
|
||||
- `SubChunk->__construct()` now accepts `int $emptyBlockId, list<PalettedBlockArray> $blockLayers, PalettedBlockArray $biomes, ?LightArray $blockLight, ?LightArray $skyLight` instead of `int, list<PalettedBlockArray>, ?LightArray, ?LightArray`
|
||||
- `io\WorldProvider->loadChunk()` now returns `LoadedChunkData` instead of `ChunkData`
|
||||
- `io\WorldProvider->getAllChunks()` now yields `LoadedChunkData` instead of `ChunkData`
|
||||
- `io\ChunkData->__construct()` now accepts `array<int, SubChunk>, bool $populated` instead of `Chunk $chunk`
|
||||
- The following API methods have been renamed:
|
||||
- `Chunk->getFullBlock()` -> `Chunk->getBlockStateId()`
|
||||
- `Chunk->setFullBlock()` -> `Chunk->setBlockStateId()`
|
||||
- `SubChunk->getFullBlock()` -> `SubChunk->getBlockStateId()`
|
||||
- `SubChunk->setFullBlock()` -> `SubChunk->setBlockStateId()`
|
||||
- The following API interface requirements have been added:
|
||||
- `public io\data\WorldData->setDisplayName(string $value) : void`
|
||||
|
||||
### `pocketmine\world\generator\object`
|
||||
- The following API methods have been removed:
|
||||
- `TreeType::fromMagicNumber()`
|
||||
- `TreeType->getMagicNumber()`
|
||||
|
||||
### `pocketmine\world\sound`
|
||||
- The following classes have been added:
|
||||
- `CopperWaxApplySound`
|
||||
- `CopperWaxRemoveSound`
|
||||
- `DyeUseSound`
|
||||
- `InkSacUseSound`
|
||||
- The following enums have new members:
|
||||
- `NoteInstrument` has new members `BELL`, `FLUTE`, `CHIME`, `XYLOPHONE`, `IRON_XYLOPHONE`, `COW_BELL`, `DIDGERIDOO`, `BIT`, `BANJO`, `PLING`
|
||||
- The following API methods have been removed:
|
||||
- `NoteInstrument::fromMagicNumber()`
|
||||
- `NoteInstrument->getMagicNumber()`
|
||||
|
||||
## Internals
|
||||
- All external usages of `KnownTranslationKeys` are now removed. All localized messages are now sent using `Translatable` objects (usually from `KnownTranslationFactory`).
|
||||
- All usages of NBT keys now use class constants instead of hardcoded strings (except for an occasional overlooked one).
|
||||
- Built-in commands now declare their names inside the class constructor, rather than accepting them as parameters. This improves code consistency.
|
||||
- Commands now use an array for permissions internally, instead of a string separated by `;`.
|
||||
- Make use of `Item->canStackWith()` instead of `Item->equals()` wherever possible, to make the code more readable.
|
||||
- Moved command timings to `Timings`.
|
||||
- Overriding of serializers and deserializers of items and blocks is now consistently disallowed. Since overriding stuff is non-cooperative, it doesn't make any sense in plugins, which must coexist with other plugins. If you want to modify the functionality of built-in stuff, you have several alternative options:
|
||||
- Use existing API (e.g. events, API methods) - most uses of overrides in PM4 and earlier were abuses that could have been done with events
|
||||
- Submit feature proposals or pull requests for new API to be added (e.g. new events)
|
||||
- Register completely custom items, and reuse behaviour from the item you want to mimic
|
||||
- Fork PocketMine-MP and alter the code directly - this way your plugins aren't pretending to be cooperative with other plugins
|
||||
- `level.dat`, block, item, entity, tile and chunk data are now tagged with a version ID as per `VersionInfo::WORLD_DATA_VERSION`. This allows the server to apply fixes to older worlds if necessary.
|
||||
- Protocol creative inventory entries are now cached in `CreativeInventoryCache` to improve performance of initial join and game mode changes.
|
||||
- Singletons in the `pocketmine\network\mcpe\convert` package have been centralized under `TypeConverter`. In the future, this will be injected where needed, allowing different converters to be used for different sessions (useful for multiversion).
|
||||
- `BlockStateDictionary` memory usage is now reduced from 9 MB to 3.5 MB using various techniques, including string reuse and binary-encoded states.
|
||||
- `NetworkSession` disconnect APIs now accept `Translatable|string` instead of `string` to allow localized disconnect messages.
|
||||
- `NetworkSession` disconnect methods have been altered to allow specifying a different disconnect reason and disconnection screen message.
|
||||
- `RuntimeBlockMapping` has been renamed to `BlockTranslator`.
|
||||
|
||||
# 5.0.1
|
||||
Released 3rd June 2023.
|
||||
|
||||
## Changes
|
||||
- [`ext-pmmpthread` version 6.0.1](https://github.com/pmmp/ext-pmmpthread/releases/tag/6.0.1) is now required (for bug fixes).
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash when breaking blocks placed in the same session (mishandled default block states).
|
||||
- Fixed spore blossoms not dropping when broken.
|
||||
- Fixed jukebox music not stopping when destroyed by an explosion.
|
||||
|
||||
## Documentation
|
||||
- Added documentation for `BlockSpreadEvent->__construct()` parameters.
|
@ -5,24 +5,20 @@
|
||||
"homepage": "https://pmmp.io",
|
||||
"license": "LGPL-3.0",
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"php": "^8.0",
|
||||
"php-64bit": "*",
|
||||
"ext-chunkutils2": "^0.3.1",
|
||||
"ext-crypto": "^0.3.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-date": "*",
|
||||
"ext-gmp": "*",
|
||||
"ext-hash": "*",
|
||||
"ext-igbinary": "^3.0.1",
|
||||
"ext-json": "*",
|
||||
"ext-leveldb": "^0.2.1 || ^0.3.0",
|
||||
"ext-mbstring": "*",
|
||||
"ext-morton": "^0.1.0",
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-phar": "*",
|
||||
"ext-pmmpthread": "^6.0.1",
|
||||
"ext-pthreads": "^4.0",
|
||||
"ext-reflection": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-sockets": "*",
|
||||
@ -33,62 +29,49 @@
|
||||
"composer-runtime-api": "^2.0",
|
||||
"adhocore/json-comment": "^1.1",
|
||||
"fgrosse/phpasn1": "^2.3",
|
||||
"pocketmine/netresearch-jsonmapper": "~v4.2.999",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~2.1.0+bedrock-1.19.80",
|
||||
"pocketmine/bedrock-data": "~2.2.0+bedrock-1.19.80",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "~1.2.0+bedrock-1.19.80",
|
||||
"pocketmine/bedrock-protocol": "~21.0.0+bedrock-1.19.80",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/binaryutils": "^0.1.9",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/color": "^0.3.0",
|
||||
"pocketmine/errorhandler": "^0.6.0",
|
||||
"pocketmine/locale-data": "~2.19.0",
|
||||
"pocketmine/log": "^0.4.0",
|
||||
"pocketmine/math": "^0.4.0",
|
||||
"pocketmine/nbt": "^0.3.2",
|
||||
"pocketmine/raklib": "^0.15.0",
|
||||
"pocketmine/raklib-ipc": "^0.2.0",
|
||||
"pocketmine/snooze": "^0.5.0",
|
||||
"ramsey/uuid": "^4.1",
|
||||
"symfony/filesystem": "^6.2"
|
||||
"pocketmine/classloader": "^0.1.0",
|
||||
"pocketmine/log": "^0.2.0",
|
||||
"pocketmine/log-pthreads": "^0.1.0",
|
||||
"pocketmine/math": "^0.2.0",
|
||||
"pocketmine/nbt": "^0.2.19",
|
||||
"pocketmine/raklib": "^0.12.7",
|
||||
"pocketmine/snooze": "^0.1.0",
|
||||
"pocketmine/spl": "^0.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.10.15",
|
||||
"phpstan/phpstan-phpunit": "^1.1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.2.0",
|
||||
"phpunit/phpunit": "^10.1"
|
||||
"phpstan/phpstan": "1.3.3",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0.0",
|
||||
"phpunit/phpunit": "^9.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"pocketmine\\": "src/"
|
||||
"": ["src"]
|
||||
},
|
||||
"files": [
|
||||
"src/CoreConstants.php"
|
||||
"src/pocketmine/CoreConstants.php",
|
||||
"src/pocketmine/GlobalConstants.php",
|
||||
"src/pocketmine/VersionInfo.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"pocketmine\\": "tests/phpunit/",
|
||||
"pocketmine\\phpstan\\rules\\": "tests/phpstan/rules"
|
||||
"pocketmine\\": "tests/phpunit/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "8.1.0"
|
||||
"php": "8.0.0"
|
||||
},
|
||||
"sort-packages": true
|
||||
},
|
||||
"scripts": {
|
||||
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/ConsoleScript.php --make ./ --relative tests/plugins/DevTools --out plugins/DevTools.phar",
|
||||
"make-devtools": "@php -dphar.readonly=0 tests/plugins/DevTools/src/DevTools/ConsoleScript.php --make tests/plugins/DevTools --out plugins/DevTools.phar",
|
||||
"make-server": [
|
||||
"@composer install --no-dev --classmap-authoritative --ignore-platform-reqs",
|
||||
"@php -dphar.readonly=0 build/server-phar.php"
|
||||
],
|
||||
"update-registry-annotations": [
|
||||
"@php build/generate-registry-annotations.php src"
|
||||
],
|
||||
"update-translation-apis": [
|
||||
"@php build/generate-known-translation-apis.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
2149
composer.lock
generated
2149
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
# Doxyfile 1.9.3
|
||||
# Doxyfile 1.8.15
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
@ -93,6 +93,14 @@ ALLOW_UNICODE_NAMES = NO
|
||||
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
|
||||
# documentation generated by doxygen is written. Doxygen will use this
|
||||
# information to generate all generated output in the proper direction.
|
||||
# Possible values are: None, LTR, RTL and Context.
|
||||
# The default value is: None.
|
||||
|
||||
OUTPUT_TEXT_DIRECTION = None
|
||||
|
||||
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
|
||||
# descriptions after the members that are listed in the file and class
|
||||
# documentation (similar to Javadoc). Set to NO to disable this.
|
||||
@ -189,16 +197,6 @@ SHORT_NAMES = NO
|
||||
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
|
||||
# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
|
||||
# such as
|
||||
# /***************
|
||||
# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
|
||||
# Javadoc-style will behave just like regular comments and it will not be
|
||||
# interpreted by doxygen.
|
||||
# The default value is: NO.
|
||||
|
||||
JAVADOC_BANNER = NO
|
||||
|
||||
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
||||
# line (until the first dot) of a Qt-style comment as the brief description. If
|
||||
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
|
||||
@ -219,14 +217,6 @@ QT_AUTOBRIEF = NO
|
||||
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
|
||||
# By default Python docstrings are displayed as preformatted text and doxygen's
|
||||
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
|
||||
# doxygen's special commands can be used and the contents of the docstring
|
||||
# documentation blocks is shown as doxygen documentation.
|
||||
# The default value is: YES.
|
||||
|
||||
PYTHON_DOCSTRING = YES
|
||||
|
||||
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
||||
# documentation from any documented member that it re-implements.
|
||||
# The default value is: YES.
|
||||
@ -250,19 +240,25 @@ TAB_SIZE = 4
|
||||
# the documentation. An alias has the form:
|
||||
# name=value
|
||||
# For example adding
|
||||
# "sideeffect=@par Side Effects:^^"
|
||||
# "sideeffect=@par Side Effects:\n"
|
||||
# will allow you to put the command \sideeffect (or @sideeffect) in the
|
||||
# documentation, which will result in a user-defined paragraph with heading
|
||||
# "Side Effects:". Note that you cannot put \n's in the value part of an alias
|
||||
# to insert newlines (in the resulting output). You can put ^^ in the value part
|
||||
# of an alias to insert a newline as if a physical newline was in the original
|
||||
# file. When you need a literal { or } or , in the value part of an alias you
|
||||
# have to escape them by means of a backslash (\), this can lead to conflicts
|
||||
# with the commands \{ and \} for these it is advised to use the version @{ and
|
||||
# @} or use a double escape (\\{ and \\})
|
||||
# "Side Effects:". You can put \n's in the value part of an alias to insert
|
||||
# newlines (in the resulting output). You can put ^^ in the value part of an
|
||||
# alias to insert a newline as if a physical newline was in the original file.
|
||||
# When you need a literal { or } or , in the value part of an alias you have to
|
||||
# escape them by means of a backslash (\), this can lead to conflicts with the
|
||||
# commands \{ and \} for these it is advised to use the version @{ and @} or use
|
||||
# a double escape (\\{ and \\})
|
||||
|
||||
ALIASES =
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
||||
# will allow you to use the command class in the itcl::class meaning.
|
||||
|
||||
TCL_SUBST =
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||
# only. Doxygen will then generate output that is more tailored for C. For
|
||||
# instance, some of the names that are used will be different. The list of all
|
||||
@ -303,22 +299,19 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
||||
# parses. With this tag you can assign which parser to use for a given
|
||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||
# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||
# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||
# default for Fortran type files). For instance to make doxygen treat .inc files
|
||||
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
|
||||
# use: inc=Fortran f=C.
|
||||
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
||||
# .inc files as Fortran files (default is PHP), and .f files as C (default is
|
||||
# Fortran), use: inc=Fortran f=C.
|
||||
#
|
||||
# Note: For files without extension you can use no_extension as a placeholder.
|
||||
#
|
||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||
# the files are not read by doxygen. When specifying no_extension you should add
|
||||
# * to the FILE_PATTERNS.
|
||||
#
|
||||
# Note see also the list of default file extension mappings.
|
||||
# the files are not read by doxygen.
|
||||
|
||||
EXTENSION_MAPPING =
|
||||
|
||||
@ -336,7 +329,7 @@ MARKDOWN_SUPPORT = YES
|
||||
# to that level are automatically included in the table of contents, even if
|
||||
# they do not have an id attribute.
|
||||
# Note: This feature currently applies only to Markdown headings.
|
||||
# Minimum value: 0, maximum value: 99, default value: 5.
|
||||
# Minimum value: 0, maximum value: 99, default value: 0.
|
||||
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
||||
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
@ -452,19 +445,6 @@ TYPEDEF_HIDES_STRUCT = NO
|
||||
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
|
||||
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
|
||||
# during processing. When set to 0 doxygen will based this on the number of
|
||||
# cores available in the system. You can set it explicitly to a value larger
|
||||
# than 0 to get more control over the balance between CPU load and processing
|
||||
# speed. At this moment only the input processing can be done using multiple
|
||||
# threads. Since this is still an experimental feature the default is set to 1,
|
||||
# which effectively disables parallel processing. Please report any issues you
|
||||
# encounter. Generating dot graphs in parallel is controlled by the
|
||||
# DOT_NUM_THREADS setting.
|
||||
# Minimum value: 0, maximum value: 32, default value: 1.
|
||||
|
||||
NUM_PROC_THREADS = 1
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
@ -485,12 +465,6 @@ EXTRACT_ALL = NO
|
||||
|
||||
EXTRACT_PRIVATE = NO
|
||||
|
||||
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
|
||||
# methods of a class will be included in the documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_PRIV_VIRTUAL = NO
|
||||
|
||||
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
||||
# scope will be included in the documentation.
|
||||
# The default value is: NO.
|
||||
@ -528,13 +502,6 @@ EXTRACT_LOCAL_METHODS = YES
|
||||
|
||||
EXTRACT_ANON_NSPACES = YES
|
||||
|
||||
# If this flag is set to YES, the name of an unnamed parameter in a declaration
|
||||
# will be determined by the corresponding definition. By default unnamed
|
||||
# parameters remain unnamed in the output.
|
||||
# The default value is: YES.
|
||||
|
||||
RESOLVE_UNNAMED_PARAMS = YES
|
||||
|
||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
||||
# undocumented members inside documented classes or files. If set to NO these
|
||||
# members will be included in the various overviews, but no documentation
|
||||
@ -552,8 +519,8 @@ HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
|
||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
||||
# declarations. If set to NO, these declarations will be included in the
|
||||
# documentation.
|
||||
# (class|struct|union) declarations. If set to NO, these declarations will be
|
||||
# included in the documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
@ -572,18 +539,11 @@ HIDE_IN_BODY_DOCS = YES
|
||||
|
||||
INTERNAL_DOCS = NO
|
||||
|
||||
# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
|
||||
# able to match the capabilities of the underlying filesystem. In case the
|
||||
# filesystem is case sensitive (i.e. it supports files in the same directory
|
||||
# whose names only differ in casing), the option must be set to YES to properly
|
||||
# deal with such files in case they appear in the input. For filesystems that
|
||||
# are not case sensitive the option should be be set to NO to properly deal with
|
||||
# output files written for symbols that only differ in casing, such as for two
|
||||
# classes, one named CLASS and the other named Class, and to also support
|
||||
# references to files without having to specify the exact matching casing. On
|
||||
# Windows (including Cygwin) and MacOS, users should typically set this option
|
||||
# to NO, whereas on Linux or other Unix flavors it should typically be set to
|
||||
# YES.
|
||||
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
|
||||
# names in lower-case letters. If set to YES, upper-case letters are also
|
||||
# allowed. This is useful if you have classes or files whose names only differ
|
||||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# and Mac users are advised to set this option to NO.
|
||||
# The default value is: system dependent.
|
||||
|
||||
CASE_SENSE_NAMES = NO
|
||||
@ -602,12 +562,6 @@ HIDE_SCOPE_NAMES = NO
|
||||
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
|
||||
# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
|
||||
# will show which file needs to be included to use the class.
|
||||
# The default value is: YES.
|
||||
|
||||
SHOW_HEADERFILE = YES
|
||||
|
||||
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
|
||||
# the files that are included by a file in the documentation of that file.
|
||||
# The default value is: YES.
|
||||
@ -765,8 +719,7 @@ FILE_VERSION_FILTER =
|
||||
# output files in an output format independent way. To create the layout file
|
||||
# that represents doxygen's defaults, run doxygen with the -l option. You can
|
||||
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
|
||||
# will be used as the name of the layout file. See also section "Changing the
|
||||
# layout of pages" for information.
|
||||
# will be used as the name of the layout file.
|
||||
#
|
||||
# Note that if you run doxygen from a directory containing a file called
|
||||
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
|
||||
@ -812,35 +765,24 @@ WARNINGS = NO
|
||||
WARN_IF_UNDOCUMENTED = NO
|
||||
|
||||
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
|
||||
# potential errors in the documentation, such as documenting some parameters in
|
||||
# a documented function twice, or documenting parameters that don't exist or
|
||||
# using markup commands wrongly.
|
||||
# potential errors in the documentation, such as not documenting some parameters
|
||||
# in a documented function, or documenting parameters that don't exist or using
|
||||
# markup commands wrongly.
|
||||
# The default value is: YES.
|
||||
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
|
||||
# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
|
||||
# function parameter documentation. If set to NO, doxygen will accept that some
|
||||
# parameters have no documentation without warning.
|
||||
# The default value is: YES.
|
||||
|
||||
WARN_IF_INCOMPLETE_DOC = YES
|
||||
|
||||
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
|
||||
# are documented, but have no documentation for their parameters or return
|
||||
# value. If set to NO, doxygen will only warn about wrong parameter
|
||||
# documentation, but not about the absence of documentation. If EXTRACT_ALL is
|
||||
# set to YES then this flag will automatically be disabled. See also
|
||||
# WARN_IF_INCOMPLETE_DOC
|
||||
# value. If set to NO, doxygen will only warn about wrong or incomplete
|
||||
# parameter documentation, but not about the absence of documentation. If
|
||||
# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_NO_PARAMDOC = NO
|
||||
|
||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
|
||||
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
|
||||
# at the end of the doxygen process doxygen will return with a non-zero status.
|
||||
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
|
||||
# a warning is encountered.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_AS_ERROR = NO
|
||||
@ -857,10 +799,7 @@ WARN_FORMAT = "$file:$line: $text"
|
||||
|
||||
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
|
||||
# messages should be written. If left blank the output is written to standard
|
||||
# error (stderr). In case the file specified cannot be opened for writing the
|
||||
# warning and error messages are written to standard error. When as file - is
|
||||
# specified the warning and error messages are written to standard output
|
||||
# (stdout).
|
||||
# error (stderr).
|
||||
|
||||
WARN_LOGFILE =
|
||||
|
||||
@ -881,8 +820,8 @@ INPUT = ../src \
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||
# documentation (see:
|
||||
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
|
||||
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
|
||||
# possible encodings.
|
||||
# The default value is: UTF-8.
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
@ -895,15 +834,11 @@ INPUT_ENCODING = UTF-8
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# read by doxygen.
|
||||
#
|
||||
# Note the list of default checked file patterns might differ from the list of
|
||||
# default file extension mappings.
|
||||
#
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
|
||||
# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
|
||||
# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
|
||||
# *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
||||
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
|
||||
FILE_PATTERNS = *.php
|
||||
|
||||
@ -948,7 +883,7 @@ EXCLUDE_PATTERNS = */bin/* \
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
# output. The symbol name can be a fully qualified name, a word, or if the
|
||||
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
||||
# ANamespace::AClass, ANamespace::*Test
|
||||
# AClass::ANamespace, ANamespace::*Test
|
||||
#
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories use the pattern */test/*
|
||||
@ -1124,24 +1059,16 @@ USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
||||
# clang parser (see:
|
||||
# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
|
||||
# performance. This can be particularly helpful with template rich C++ code for
|
||||
# which doxygen's built-in parser lacks the necessary type information.
|
||||
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
|
||||
# cost of reduced performance. This can be particularly helpful with template
|
||||
# rich C++ code for which doxygen's built-in parser lacks the necessary type
|
||||
# information.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
# The default value is: NO.
|
||||
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
|
||||
# tag is set to YES then doxygen will add the directory of each input to the
|
||||
# include path.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_ADD_INC_PATHS = YES
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||
# line options that you would normally use when invoking the compiler. Note that
|
||||
# the include paths will already be set by doxygen for the files and directories
|
||||
@ -1151,13 +1078,10 @@ CLANG_ADD_INC_PATHS = YES
|
||||
CLANG_OPTIONS =
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the clang parser with the
|
||||
# path to the directory containing a file called compile_commands.json. This
|
||||
# file is the compilation database (see:
|
||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
|
||||
# options used when the source files were built. This is equivalent to
|
||||
# specifying the -p option to a clang tool, such as clang-check. These options
|
||||
# will then be passed to the parser. Any options specified with CLANG_OPTIONS
|
||||
# will be added as well.
|
||||
# path to the compilation database (see:
|
||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
|
||||
# were built. This is equivalent to specifying the "-p" option to a clang tool,
|
||||
# such as clang-check. These options will then be passed to the parser.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
|
||||
@ -1174,6 +1098,13 @@ CLANG_DATABASE_PATH =
|
||||
|
||||
ALPHABETICAL_INDEX = YES
|
||||
|
||||
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
||||
# which the alphabetical index list will be split.
|
||||
# Minimum value: 1, maximum value: 20, default value: 5.
|
||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
||||
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
|
||||
# In case all classes in a project start with a common prefix, all classes will
|
||||
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
||||
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
||||
@ -1273,7 +1204,7 @@ HTML_EXTRA_FILES =
|
||||
|
||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||
# will adjust the colors in the style sheet and background images according to
|
||||
# this color. Hue is specified as an angle on a color-wheel, see
|
||||
# this color. Hue is specified as an angle on a colorwheel, see
|
||||
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
||||
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
||||
# purple, and 360 is red again.
|
||||
@ -1283,7 +1214,7 @@ HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
|
||||
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
|
||||
# in the HTML output. For a value of 0 the output will use gray-scales only. A
|
||||
# in the HTML output. For a value of 0 the output will use grayscales only. A
|
||||
# value of 255 will produce the most vivid colors.
|
||||
# Minimum value: 0, maximum value: 255, default value: 100.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
@ -1308,13 +1239,13 @@ HTML_COLORSTYLE_GAMMA = 80
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_TIMESTAMP = NO
|
||||
HTML_TIMESTAMP = YES
|
||||
|
||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
||||
# documentation will contain a main index with vertical navigation menus that
|
||||
# are dynamically created via JavaScript. If disabled, the navigation index will
|
||||
# are dynamically created via Javascript. If disabled, the navigation index will
|
||||
# consists of multiple levels of tabs that are statically embedded in every HTML
|
||||
# page. Disable this option to support browsers that do not have JavaScript,
|
||||
# page. Disable this option to support browsers that do not have Javascript,
|
||||
# like the Qt help browser.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
@ -1344,11 +1275,10 @@ HTML_INDEX_NUM_ENTRIES = 100
|
||||
|
||||
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
||||
# generated that can be used as input for Apple's Xcode 3 integrated development
|
||||
# environment (see:
|
||||
# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
|
||||
# create a documentation set, doxygen will generate a Makefile in the HTML
|
||||
# output directory. Running make will produce the docset in that directory and
|
||||
# running make install will install the docset in
|
||||
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
|
||||
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
||||
# Makefile in the HTML output directory. Running make will produce the docset in
|
||||
# that directory and running make install will install the docset in
|
||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
||||
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
||||
# genXcode/_index.html for more information.
|
||||
@ -1365,13 +1295,6 @@ GENERATE_DOCSET = NO
|
||||
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
|
||||
# This tag determines the URL of the docset feed. A documentation feed provides
|
||||
# an umbrella under which multiple documentation sets from a single provider
|
||||
# (such as a company or product suite) can be grouped.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
|
||||
DOCSET_FEEDURL =
|
||||
|
||||
# This tag specifies a string that should uniquely identify the documentation
|
||||
# set bundle. This should be a reverse domain-name style string, e.g.
|
||||
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
|
||||
@ -1397,12 +1320,8 @@ DOCSET_PUBLISHER_NAME = Publisher
|
||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||
# on Windows. In the beginning of 2021 Microsoft took the original page, with
|
||||
# a.o. the download links, offline the HTML help workshop was already many years
|
||||
# in maintenance mode). You can download the HTML help workshop from the web
|
||||
# archives at Installation executable (see:
|
||||
# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
|
||||
# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
|
||||
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
||||
# Windows.
|
||||
#
|
||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
||||
@ -1432,7 +1351,7 @@ CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
|
||||
# The GENERATE_CHI flag controls if a separate .chi index file is generated
|
||||
# (YES) or that it should be included in the main .chm file (NO).
|
||||
# (YES) or that it should be included in the master .chm file (NO).
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
@ -1477,8 +1396,7 @@ QCH_FILE =
|
||||
|
||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||
# Project output. For more information please see Qt Help Project / Namespace
|
||||
# (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@ -1486,8 +1404,8 @@ QHP_NAMESPACE = org.doxygen.Project
|
||||
|
||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
||||
# Help Project output. For more information please see Qt Help Project / Virtual
|
||||
# Folders (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
|
||||
# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
||||
# folders).
|
||||
# The default value is: doc.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@ -1495,30 +1413,30 @@ QHP_VIRTUAL_FOLDER = doc
|
||||
|
||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||
# filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_CUST_FILTER_NAME =
|
||||
|
||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
|
||||
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
||||
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
|
||||
# The QHG_LOCATION tag can be used to specify the location (absolute path
|
||||
# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
|
||||
# run qhelpgenerator on the generated .qhp file.
|
||||
# The QHG_LOCATION tag can be used to specify the location of Qt's
|
||||
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
|
||||
# generated .qhp file.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHG_LOCATION =
|
||||
@ -1561,28 +1479,16 @@ DISABLE_INDEX = NO
|
||||
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
|
||||
# (i.e. any modern browser). Windows users are probably better off using the
|
||||
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
|
||||
# further fine tune the look of the index (see "Fine-tuning the output"). As an
|
||||
# example, the default style sheet generated by doxygen has an example that
|
||||
# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
|
||||
# Since the tree basically has the same information as the tab index, you could
|
||||
# consider setting DISABLE_INDEX to YES when enabling this option.
|
||||
# further fine-tune the look of the index. As an example, the default style
|
||||
# sheet generated by doxygen has an example that shows how to put an image at
|
||||
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
|
||||
# the same information as the tab index, you could consider setting
|
||||
# DISABLE_INDEX to YES when enabling this option.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
GENERATE_TREEVIEW = YES
|
||||
|
||||
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
|
||||
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
|
||||
# area (value NO) or if it should extend to the full height of the window (value
|
||||
# YES). Setting this to YES gives a layout similar to
|
||||
# https://docs.readthedocs.io with more room for contents, but less room for the
|
||||
# project logo, title, and description. If either GENERATE_TREEVIEW or
|
||||
# DISABLE_INDEX is set to NO, this option has no effect.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
FULL_SIDEBAR = NO
|
||||
|
||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||
# doxygen will group on one line in the generated HTML documentation.
|
||||
#
|
||||
@ -1607,24 +1513,6 @@ TREEVIEW_WIDTH = 250
|
||||
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
|
||||
# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
|
||||
# addresses.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
OBFUSCATE_EMAILS = YES
|
||||
|
||||
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
|
||||
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
|
||||
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
|
||||
# the HTML output. These images will generally look nicer at scaled resolutions.
|
||||
# Possible values are: png (the default) and svg (looks nicer but requires the
|
||||
# pdf2svg or inkscape tool).
|
||||
# The default value is: png.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_FORMULA_FORMAT = png
|
||||
|
||||
# Use this tag to change the font size of LaTeX formulas included as images in
|
||||
# the HTML documentation. When you change the font size after a successful
|
||||
# doxygen run you need to manually remove any form_*.png images from the HTML
|
||||
@ -1645,14 +1533,8 @@ FORMULA_FONTSIZE = 10
|
||||
|
||||
FORMULA_TRANSPARENT = YES
|
||||
|
||||
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
|
||||
# to create new LaTeX commands to be used in formulas as building blocks. See
|
||||
# the section "Including formulas" for details.
|
||||
|
||||
FORMULA_MACROFILE =
|
||||
|
||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
||||
# https://www.mathjax.org) which uses client side JavaScript for the rendering
|
||||
# https://www.mathjax.org) which uses client side Javascript for the rendering
|
||||
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
||||
# installed or if you want to formulas look prettier in the HTML output. When
|
||||
# enabled you may also need to install MathJax separately and configure the path
|
||||
@ -1662,29 +1544,11 @@ FORMULA_MACROFILE =
|
||||
|
||||
USE_MATHJAX = YES
|
||||
|
||||
# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
|
||||
# Note that the different versions of MathJax have different requirements with
|
||||
# regards to the different settings, so it is possible that also other MathJax
|
||||
# settings have to be changed when switching between the different MathJax
|
||||
# versions.
|
||||
# Possible values are: MathJax_2 and MathJax_3.
|
||||
# The default value is: MathJax_2.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_VERSION = MathJax_2
|
||||
|
||||
# When MathJax is enabled you can set the default output format to be used for
|
||||
# the MathJax output. For more details about the output format see MathJax
|
||||
# version 2 (see:
|
||||
# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
|
||||
# (see:
|
||||
# http://docs.mathjax.org/en/latest/web/components/output.html).
|
||||
# the MathJax output. See the MathJax site (see:
|
||||
# http://docs.mathjax.org/en/latest/output.html) for more details.
|
||||
# Possible values are: HTML-CSS (which is slower, but has the best
|
||||
# compatibility. This is the name for Mathjax version 2, for MathJax version 3
|
||||
# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
|
||||
# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
|
||||
# is the name for Mathjax version 3, for MathJax version 2 this will be
|
||||
# translated into HTML-CSS) and SVG.
|
||||
# compatibility), NativeMML (i.e. MathML) and SVG.
|
||||
# The default value is: HTML-CSS.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
@ -1697,29 +1561,22 @@ MATHJAX_FORMAT = HTML-CSS
|
||||
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
|
||||
# Content Delivery Network so you can quickly see the result without installing
|
||||
# MathJax. However, it is strongly recommended to install a local copy of
|
||||
# MathJax from https://www.mathjax.org before deployment. The default value is:
|
||||
# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
|
||||
# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
|
||||
# MathJax from https://www.mathjax.org before deployment.
|
||||
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
|
||||
|
||||
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
|
||||
# extension names that should be enabled during MathJax rendering. For example
|
||||
# for MathJax version 2 (see
|
||||
# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
|
||||
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
|
||||
# For example for MathJax version 3 (see
|
||||
# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
|
||||
# MATHJAX_EXTENSIONS = ams
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_EXTENSIONS =
|
||||
|
||||
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
||||
# of code that will be used on startup of the MathJax code. See the MathJax site
|
||||
# (see:
|
||||
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
|
||||
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
|
||||
# example see the documentation.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
@ -1747,7 +1604,7 @@ MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
|
||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||
# implemented using a web server instead of a web client using JavaScript. There
|
||||
# implemented using a web server instead of a web client using Javascript. There
|
||||
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||
@ -1766,8 +1623,7 @@ SERVER_BASED_SEARCH = NO
|
||||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see:
|
||||
# https://xapian.org/).
|
||||
# Xapian (see: https://xapian.org/).
|
||||
#
|
||||
# See the section "External Indexing and Searching" for details.
|
||||
# The default value is: NO.
|
||||
@ -1780,9 +1636,8 @@ EXTERNAL_SEARCH = NO
|
||||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see:
|
||||
# https://xapian.org/). See the section "External Indexing and Searching" for
|
||||
# details.
|
||||
# Xapian (see: https://xapian.org/). See the section "External Indexing and
|
||||
# Searching" for details.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
SEARCHENGINE_URL =
|
||||
@ -1853,11 +1708,10 @@ LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
|
||||
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
|
||||
# generate index for LaTeX. In case there is no backslash (\) as first character
|
||||
# it will be automatically added in the LaTeX code.
|
||||
# generate index for LaTeX.
|
||||
# Note: This tag is used in the generated output file (.tex).
|
||||
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
|
||||
# The default value is: makeindex.
|
||||
# The default value is: \makeindex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_MAKEINDEX_CMD = \makeindex
|
||||
@ -1891,31 +1745,29 @@ PAPER_TYPE = a4
|
||||
|
||||
EXTRA_PACKAGES =
|
||||
|
||||
# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
|
||||
# the generated LaTeX document. The header should contain everything until the
|
||||
# first chapter. If it is left blank doxygen will generate a standard header. It
|
||||
# is highly recommended to start with a default header using
|
||||
# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
|
||||
# and then modify the file new_header.tex. See also section "Doxygen usage" for
|
||||
# information on how to generate the default header that doxygen normally uses.
|
||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
|
||||
# generated LaTeX document. The header should contain everything until the first
|
||||
# chapter. If it is left blank doxygen will generate a standard header. See
|
||||
# section "Doxygen usage" for information on how to let doxygen write the
|
||||
# default header to a separate file.
|
||||
#
|
||||
# Note: Only use a user-defined header if you know what you are doing!
|
||||
# Note: The header is subject to change so you typically have to regenerate the
|
||||
# default header when upgrading to a newer version of doxygen. The following
|
||||
# commands have a special meaning inside the header (and footer): For a
|
||||
# description of the possible markers and block names see the documentation.
|
||||
# Note: Only use a user-defined header if you know what you are doing! The
|
||||
# following commands have a special meaning inside the header: $title,
|
||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
||||
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
|
||||
# string, for the replacement values of the other commands the user is referred
|
||||
# to HTML_HEADER.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_HEADER =
|
||||
|
||||
# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
|
||||
# the generated LaTeX document. The footer should contain everything after the
|
||||
# last chapter. If it is left blank doxygen will generate a standard footer. See
|
||||
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
|
||||
# generated LaTeX document. The footer should contain everything after the last
|
||||
# chapter. If it is left blank doxygen will generate a standard footer. See
|
||||
# LATEX_HEADER for more information on how to generate a default footer and what
|
||||
# special commands can be used inside the footer. See also section "Doxygen
|
||||
# usage" for information on how to generate the default footer that doxygen
|
||||
# normally uses. Note: Only use a user-defined footer if you know what you are
|
||||
# doing!
|
||||
# special commands can be used inside the footer.
|
||||
#
|
||||
# Note: Only use a user-defined footer if you know what you are doing!
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_FOOTER =
|
||||
@ -1948,11 +1800,9 @@ LATEX_EXTRA_FILES =
|
||||
|
||||
PDF_HYPERLINKS = YES
|
||||
|
||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
|
||||
# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
|
||||
# files. Set this option to YES, to get a higher quality PDF documentation.
|
||||
#
|
||||
# See also section LATEX_CMD_NAME for selecting the engine.
|
||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
||||
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
|
||||
# higher quality PDF documentation.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
@ -1960,7 +1810,8 @@ USE_PDFLATEX = YES
|
||||
|
||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
|
||||
# command to the generated LaTeX files. This will instruct LaTeX to keep running
|
||||
# if errors occur, instead of asking the user for help.
|
||||
# if errors occur, instead of asking the user for help. This option is also used
|
||||
# when generating formulas in HTML.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
@ -1973,6 +1824,16 @@ LATEX_BATCHMODE = NO
|
||||
|
||||
LATEX_HIDE_INDICES = NO
|
||||
|
||||
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
|
||||
# code with syntax highlighting in the LaTeX output.
|
||||
#
|
||||
# Note that which sources are shown also depends on other settings such as
|
||||
# SOURCE_BROWSER.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_SOURCE_CODE = NO
|
||||
|
||||
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
||||
# bibliography, e.g. plainnat, or ieeetr. See
|
||||
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
||||
@ -2053,6 +1914,16 @@ RTF_STYLESHEET_FILE =
|
||||
|
||||
RTF_EXTENSIONS_FILE =
|
||||
|
||||
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
|
||||
# with syntax highlighting in the RTF output.
|
||||
#
|
||||
# Note that which sources are shown also depends on other settings such as
|
||||
# SOURCE_BROWSER.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_SOURCE_CODE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
@ -2149,6 +2020,15 @@ GENERATE_DOCBOOK = NO
|
||||
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
|
||||
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
|
||||
# program listings (including syntax highlighting and cross-referencing
|
||||
# information) to the DOCBOOK output. Note that enabling this will significantly
|
||||
# increase the size of the DOCBOOK output.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
|
||||
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
@ -2323,10 +2203,34 @@ EXTERNAL_GROUPS = YES
|
||||
|
||||
EXTERNAL_PAGES = YES
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of 'which perl').
|
||||
# The default file (with absolute path) is: /usr/bin/perl.
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
|
||||
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
|
||||
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
|
||||
# disabled, but it is recommended to install and use dot, since it yields more
|
||||
# powerful graphs.
|
||||
# The default value is: YES.
|
||||
|
||||
CLASS_DIAGRAMS = NO
|
||||
|
||||
# You can define message sequence charts within doxygen comments using the \msc
|
||||
# command. Doxygen will then run the mscgen tool (see:
|
||||
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
|
||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
|
||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
||||
# default search path.
|
||||
|
||||
MSCGEN_PATH =
|
||||
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
@ -2383,14 +2287,11 @@ DOT_FONTSIZE = 10
|
||||
|
||||
DOT_FONTPATH =
|
||||
|
||||
# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
|
||||
# graph for each documented class showing the direct and indirect inheritance
|
||||
# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
|
||||
# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
|
||||
# to TEXT the direct and indirect inheritance relations will be shown as texts /
|
||||
# links.
|
||||
# Possible values are: NO, YES, TEXT and GRAPH.
|
||||
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
|
||||
# each documented class showing the direct and indirect inheritance relations.
|
||||
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
CLASS_GRAPH = YES
|
||||
|
||||
@ -2427,31 +2328,9 @@ UML_LOOK = YES
|
||||
# but if the number exceeds 15, the total amount of fields shown is limited to
|
||||
# 10.
|
||||
# Minimum value: 0, maximum value: 100, default value: 10.
|
||||
# This tag requires that the tag UML_LOOK is set to YES.
|
||||
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
|
||||
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
|
||||
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
|
||||
# tag is set to YES, doxygen will add type and arguments for attributes and
|
||||
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
|
||||
# will not generate fields with class member information in the UML graphs. The
|
||||
# class diagrams will look similar to the default class diagrams but using UML
|
||||
# notation for the relationships.
|
||||
# Possible values are: NO, YES and NONE.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag UML_LOOK is set to YES.
|
||||
|
||||
DOT_UML_DETAILS = NO
|
||||
|
||||
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
|
||||
# to display on a single line. If the actual line length exceeds this threshold
|
||||
# significantly it will wrapped across multiple lines. Some heuristics are apply
|
||||
# to avoid ugly line breaks.
|
||||
# Minimum value: 0, maximum value: 1000, default value: 17.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_WRAP_THRESHOLD = 17
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
|
||||
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
||||
# collaboration graphs will show the relations between templates and their
|
||||
@ -2519,13 +2398,6 @@ GRAPHICAL_HIERARCHY = YES
|
||||
|
||||
DIRECTORY_GRAPH = YES
|
||||
|
||||
# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
|
||||
# of child directories generated in directory dependency graphs by dot.
|
||||
# Minimum value: 1, maximum value: 25, default value: 1.
|
||||
# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
|
||||
|
||||
DIR_GRAPH_MAX_DEPTH = 1
|
||||
|
||||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
||||
# generated by dot. For an explanation of the image formats see the section
|
||||
# output formats in the documentation of the dot tool (Graphviz (see:
|
||||
@ -2579,10 +2451,10 @@ MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
|
||||
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
|
||||
# path where java can find the plantuml.jar file or to the filename of jar file
|
||||
# to be used. If left blank, it is assumed PlantUML is not used or called during
|
||||
# a preprocessing step. Doxygen will generate a warning when it encounters a
|
||||
# \startuml command in this case and will not generate output for the diagram.
|
||||
# path where java can find the plantuml.jar file. If left blank, it is assumed
|
||||
# PlantUML is not used or called during a preprocessing step. Doxygen will
|
||||
# generate a warning when it encounters a \startuml command in this case and
|
||||
# will not generate output for the diagram.
|
||||
|
||||
PLANTUML_JAR_PATH =
|
||||
|
||||
@ -2644,18 +2516,14 @@ DOT_MULTI_TARGETS = YES
|
||||
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
|
||||
# explaining the meaning of the various boxes and arrows in the dot generated
|
||||
# graphs.
|
||||
# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
|
||||
# graphical representation for inheritance and collaboration diagrams is used.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
GENERATE_LEGEND = YES
|
||||
|
||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
|
||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
|
||||
# files that are used to generate the various graphs.
|
||||
#
|
||||
# Note: This setting is not only used for dot files but also for msc temporary
|
||||
# files.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_CLEANUP = YES
|
||||
|
@ -1,19 +1,15 @@
|
||||
includes:
|
||||
- tests/phpstan/analyse-for-current-php-version.neon.php
|
||||
- tests/phpstan/configs/actual-problems.neon
|
||||
- tests/phpstan/configs/impossible-generics.neon
|
||||
- tests/phpstan/configs/gc-hacks.neon
|
||||
- tests/phpstan/configs/php-bugs.neon
|
||||
- tests/phpstan/configs/phpstan-bugs.neon
|
||||
- tests/phpstan/configs/phpunit-wiring-tests.neon
|
||||
- tests/phpstan/configs/runtime-type-checks.neon
|
||||
- tests/phpstan/configs/spl-fixed-array-sucks.neon
|
||||
- vendor/phpstan/phpstan-phpunit/extension.neon
|
||||
- vendor/phpstan/phpstan-phpunit/rules.neon
|
||||
- vendor/phpstan/phpstan-strict-rules/rules.neon
|
||||
|
||||
rules:
|
||||
- pocketmine\phpstan\rules\DisallowEnumComparisonRule
|
||||
- pocketmine\phpstan\rules\UnsafeForeachArrayOfStringRule
|
||||
# - pocketmine\phpstan\rules\ThreadedSupportedTypesRule
|
||||
|
||||
parameters:
|
||||
level: 9
|
||||
checkMissingCallableSignature: true
|
||||
@ -23,28 +19,28 @@ parameters:
|
||||
scanDirectories:
|
||||
- build
|
||||
- tests/plugins/TesterPlugin
|
||||
- tools
|
||||
scanFiles:
|
||||
- src/PocketMine.php
|
||||
- src/pocketmine/PocketMine.php
|
||||
paths:
|
||||
- build
|
||||
- src
|
||||
- tests/phpstan/rules
|
||||
- tests/phpunit
|
||||
- tests/plugins/TesterPlugin
|
||||
- tools
|
||||
excludePaths:
|
||||
analyseAndScan:
|
||||
- build/php
|
||||
- build/preprocessor
|
||||
analyse:
|
||||
- src/pocketmine/block/StoneSlab.php #overrides STONE constant
|
||||
- src/pocketmine/item/Potion.php #overrides WATER constant
|
||||
dynamicConstantNames:
|
||||
- pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD
|
||||
- pocketmine\DEBUG
|
||||
- pocketmine\IS_DEVELOPMENT_BUILD
|
||||
stubFiles:
|
||||
- tests/phpstan/stubs/JsonMapper.stub
|
||||
- tests/phpstan/stubs/chunkutils.stub
|
||||
- tests/phpstan/stubs/leveldb.stub
|
||||
- tests/phpstan/stubs/phpasn1.stub
|
||||
- tests/phpstan/stubs/pmmpthread.stub
|
||||
- tests/phpstan/stubs/pthreads.stub
|
||||
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
||||
staticReflectionClassNamePatterns:
|
||||
- "#^COM$#"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
||||
#This configuration file allows you to control which plugins are loaded on your server.
|
||||
|
||||
#List behaviour
|
||||
# - blacklist: Only plugins which ARE NOT listed will load.
|
||||
# - whitelist: Only plugins which ARE listed will load.
|
||||
mode: blacklist
|
||||
#List names of plugins here.
|
||||
plugins: []
|
@ -1,223 +0,0 @@
|
||||
# Main configuration file for PocketMine-MP
|
||||
# These settings are the ones that cannot be included in server.properties
|
||||
# Some of these settings are safe, others can break your server if modified incorrectly
|
||||
# New settings/defaults won't appear automatically in this file when upgrading.
|
||||
|
||||
settings:
|
||||
#Whether to send all strings translated to server locale or let the device handle them
|
||||
force-language: false
|
||||
shutdown-message: "Server closed"
|
||||
#Allow listing plugins via Query
|
||||
query-plugins: true
|
||||
#Enable plugin and core profiling by default
|
||||
enable-profiling: false
|
||||
#Will only add results when tick measurement is below or equal to given value (default 20)
|
||||
profile-report-trigger: 20
|
||||
#Number of AsyncTask workers.
|
||||
#Used for plugin asynchronous tasks, world generation, compression and web communication.
|
||||
#Set this approximately to your number of cores.
|
||||
#If set to auto, it'll try to detect the number of cores (or use 2)
|
||||
async-workers: auto
|
||||
#Whether to allow running development builds. Dev builds might crash, break your plugins, corrupt your world and more.
|
||||
#It is recommended to avoid using development builds where possible.
|
||||
enable-dev-builds: false
|
||||
|
||||
memory:
|
||||
#Global soft memory limit in megabytes. Set to 0 to disable
|
||||
#This will trigger low-memory-triggers and fire an event to free memory when the usage goes over this
|
||||
global-limit: 0
|
||||
|
||||
#Main thread soft memory limit in megabytes. Set to 0 to disable
|
||||
#This will trigger low-memory-triggers and fire an event to free memory when the usage goes over this
|
||||
main-limit: 0
|
||||
|
||||
#Main thread hard memory limit in megabytes. Set to 0 to disable
|
||||
#This will stop the server when the limit is surpassed
|
||||
main-hard-limit: 1024
|
||||
|
||||
#AsyncWorker threads' hard memory limit in megabytes. Set to 0 to disable
|
||||
#This will crash the task currently executing on the worker if the task exceeds the limit
|
||||
#NOTE: THIS LIMIT APPLIES PER WORKER, NOT TO THE WHOLE PROCESS.
|
||||
async-worker-hard-limit: 256
|
||||
|
||||
#Period in ticks to check memory (default 1 second)
|
||||
check-rate: 20
|
||||
|
||||
#Continue firing low-memory-triggers and event while on low memory
|
||||
continuous-trigger: true
|
||||
|
||||
#Only if memory.continuous-trigger is enabled. Specifies the rate in memory.check-rate steps (default 30 seconds)
|
||||
continuous-trigger-rate: 30
|
||||
|
||||
garbage-collection:
|
||||
#Period in ticks to fire the garbage collector manually (default 30 minutes), set to 0 to disable
|
||||
#This only affects the main thread. Other threads should fire their own collections
|
||||
period: 36000
|
||||
|
||||
#Fire asynchronous tasks to collect garbage from workers
|
||||
collect-async-worker: true
|
||||
|
||||
#Trigger on low memory
|
||||
low-memory-trigger: true
|
||||
|
||||
#Settings controlling memory dump handling.
|
||||
memory-dump:
|
||||
#Dump memory from async workers as well as the main thread. If you have issues with segfaults when dumping memory, disable this setting.
|
||||
dump-async-worker: true
|
||||
|
||||
max-chunks:
|
||||
#Cap maximum render distance per player when low memory is triggered. Set to 0 to disable cap.
|
||||
chunk-radius: 4
|
||||
|
||||
#Do chunk garbage collection on trigger
|
||||
trigger-chunk-collect: true
|
||||
|
||||
world-caches:
|
||||
#Disallow adding to world chunk-packet caches when memory is low
|
||||
disable-chunk-cache: true
|
||||
#Clear world caches when memory is low
|
||||
low-memory-trigger: true
|
||||
|
||||
|
||||
network:
|
||||
#Threshold for batching packets, in bytes. Only these packets will be compressed
|
||||
#Set to 0 to compress everything, -1 to disable.
|
||||
batch-threshold: 256
|
||||
#Compression level used when sending batched packets. Higher = more CPU, less bandwidth usage
|
||||
compression-level: 6
|
||||
#Use AsyncTasks for compression during the main game session. Increases latency, but may reduce main thread load
|
||||
async-compression: false
|
||||
#Threshold for async compression, in bytes. Only packets larger than this will be compressed asynchronously
|
||||
#Due to large overhead of AsyncTask, async compression isn't worth it except for large packets
|
||||
async-compression-threshold: 10000
|
||||
#Experimental. Use UPnP to automatically port forward
|
||||
upnp-forwarding: false
|
||||
#Maximum size in bytes of packets sent over the network (default 1492 bytes). Packets larger than this will be
|
||||
#fragmented or split into smaller parts. Clients can request MTU sizes up to but not more than this number.
|
||||
max-mtu-size: 1492
|
||||
#Enable encryption of Minecraft network traffic. This has an impact on performance, but prevents hackers from stealing sessions and pretending to be other players.
|
||||
#DO NOT DISABLE THIS unless you understand the risks involved.
|
||||
enable-encryption: true
|
||||
|
||||
debug:
|
||||
#If > 1, it will show debug messages in the console
|
||||
level: 1
|
||||
|
||||
player:
|
||||
#Choose whether to enable player data saving.
|
||||
save-player-data: true
|
||||
#If true, checks that joining players' Xbox user ID (XUID) match what was previously recorded.
|
||||
#This also prevents non-XBL players using XBL players' usernames to steal their data on servers with xbox-auth=off.
|
||||
verify-xuid: true
|
||||
|
||||
level-settings:
|
||||
#The default format that worlds will use when created
|
||||
default-format: leveldb
|
||||
|
||||
chunk-sending:
|
||||
#To change server normal render distance, change view-distance in server.properties.
|
||||
#Amount of chunks sent to players per tick
|
||||
per-tick: 4
|
||||
#Radius of chunks that need to be sent before spawning the player
|
||||
spawn-radius: 4
|
||||
|
||||
chunk-ticking:
|
||||
#Radius of chunks around a player to tick
|
||||
tick-radius: 3
|
||||
#Number of blocks inside ticking areas' subchunks that get ticked every tick. Higher values will accelerate events
|
||||
#like tree and plant growth, but at a higher performance cost.
|
||||
blocks-per-subchunk-per-tick: 3
|
||||
#IDs of blocks not to perform random ticking on.
|
||||
disable-block-ticking:
|
||||
#- grass
|
||||
#- ice
|
||||
#- fire
|
||||
|
||||
chunk-generation:
|
||||
#Max. amount of chunks in the waiting queue to be populated
|
||||
population-queue-size: 32
|
||||
|
||||
ticks-per:
|
||||
autosave: 6000
|
||||
|
||||
auto-report:
|
||||
#Send crash reports for processing
|
||||
enabled: true
|
||||
send-code: true
|
||||
send-settings: true
|
||||
send-phpinfo: false
|
||||
use-https: true
|
||||
host: crash.pmmp.io
|
||||
|
||||
anonymous-statistics:
|
||||
#Sends anonymous statistics for data aggregation, plugin usage tracking
|
||||
enabled: false #TODO: re-enable this when we have a new stats host
|
||||
host: stats.pocketmine.net
|
||||
|
||||
auto-updater:
|
||||
enabled: true
|
||||
on-update:
|
||||
warn-console: true
|
||||
#Can be development, alpha, beta or stable.
|
||||
preferred-channel: stable
|
||||
#If using a development version, it will suggest changing the channel
|
||||
suggest-channels: true
|
||||
host: update.pmmp.io
|
||||
|
||||
timings:
|
||||
#Choose the host to use for viewing your timings results.
|
||||
host: timings.pmmp.io
|
||||
|
||||
console:
|
||||
#Whether to accept commands via the console. If disabled, anything typed on the console will be ignored.
|
||||
#Useful to save resources on headless servers where the console is never used (e.g. hosted server, Docker, etc.)
|
||||
enable-input: true
|
||||
#Choose whether to enable server stats reporting on the console title.
|
||||
#NOTE: The title ticker will be disabled regardless if console colours are not enabled.
|
||||
title-tick: true
|
||||
|
||||
aliases:
|
||||
##This section allows you to add, remove or remap command aliases.
|
||||
##A single alias can call one or more other commands (or aliases).
|
||||
##Aliases defined here will override any command aliases declared by plugins or PocketMine-MP itself.
|
||||
|
||||
##To remove an alias, set it to [], like so (note that prefixed aliases like "pocketmine:stop" will remain and can't
|
||||
##be removed):
|
||||
#stop: []
|
||||
|
||||
##Commands are not removed, only their aliases. You can still refer to a command using its full (prefixed)
|
||||
##name, even if all its aliases are overwritten. The full name is usually something like "pocketmine:commandname" or
|
||||
##"pluginname:commandname".
|
||||
#abort: [pocketmine:stop]
|
||||
|
||||
##To add an alias, list the command(s) that it calls:
|
||||
#showtheversion: [version]
|
||||
#savestop: [save-all, stop]
|
||||
|
||||
##To invoke another command with arguments, use $1 to pass the first argument, $2 for the second etc:
|
||||
#giveadmin: [op $1] ## `giveadmin alex` -> `op alex`
|
||||
#kill: [suicide, say "I tried to kill $1"] ## `kill alex` -> `suicide` + `say "I tried to kill alex"`
|
||||
#giverandom: [give $1 $2, say "Someone has just received a $2!"] ## `giverandom alex diamond` -> `give alex diamond` + `say "Someone has just received a diamond!"`
|
||||
|
||||
##To make arguments mandatory (so that the command fails if they are not provided), use $$, e.g. $$1, $$2:
|
||||
#makeadmin: [op $$1] ## `makeadmin alex` -> `op alex`, `makeadmin` with no arguments = error
|
||||
|
||||
##To pass through a range of arguments, put a - (hyphen) after the index:
|
||||
#tpalias: [tp $1-] ## `tpalias 256 70 256` -> `tp 256 70 256` - this passes arguments 1 and everything after it to the `tp` command
|
||||
|
||||
##To change an existing command alias and make it do something else:
|
||||
#tp: [suicide]
|
||||
|
||||
worlds:
|
||||
#These settings will override the generator set in server.properties and allows loading multiple worlds
|
||||
#Example:
|
||||
#world:
|
||||
# seed: 404
|
||||
# generator: FLAT
|
||||
# preset: 2;bedrock,59xstone,3xdirt,grass;1
|
||||
|
||||
plugins:
|
||||
#Setting this to true will cause the legacy structure to be used where plugin data is placed inside the --plugins dir.
|
||||
#False will place plugin data under plugin_data under --data.
|
||||
#This option exists for backwards compatibility with existing installations.
|
||||
legacy-data-dir: false
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use function define;
|
||||
use function defined;
|
||||
use function dirname;
|
||||
|
||||
// composer autoload doesn't use require_once and also pthreads can inherit things
|
||||
if(defined('pocketmine\_CORE_CONSTANTS_INCLUDED')){
|
||||
return;
|
||||
}
|
||||
define('pocketmine\_CORE_CONSTANTS_INCLUDED', true);
|
||||
|
||||
define('pocketmine\PATH', dirname(__DIR__) . '/');
|
||||
define('pocketmine\RESOURCE_PATH', dirname(__DIR__) . '/resources/');
|
||||
define('pocketmine\BEDROCK_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-data/');
|
||||
define('pocketmine\LOCALE_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/locale-data/');
|
||||
define('pocketmine\BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-block-upgrade-schema/');
|
||||
define('pocketmine\BEDROCK_ITEM_UPGRADE_SCHEMA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-item-upgrade-schema/');
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__) . '/vendor/autoload.php');
|
@ -1,520 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\event\server\LowMemoryEvent;
|
||||
use pocketmine\network\mcpe\cache\ChunkCache;
|
||||
use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||
use pocketmine\scheduler\GarbageCollectionTask;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\Utils;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function arsort;
|
||||
use function count;
|
||||
use function fclose;
|
||||
use function file_exists;
|
||||
use function file_put_contents;
|
||||
use function fopen;
|
||||
use function fwrite;
|
||||
use function gc_collect_cycles;
|
||||
use function gc_disable;
|
||||
use function gc_enable;
|
||||
use function gc_mem_caches;
|
||||
use function get_class;
|
||||
use function get_declared_classes;
|
||||
use function get_defined_functions;
|
||||
use function ini_get;
|
||||
use function ini_set;
|
||||
use function intdiv;
|
||||
use function is_array;
|
||||
use function is_float;
|
||||
use function is_object;
|
||||
use function is_resource;
|
||||
use function is_string;
|
||||
use function json_encode;
|
||||
use function mb_strtoupper;
|
||||
use function min;
|
||||
use function mkdir;
|
||||
use function preg_match;
|
||||
use function print_r;
|
||||
use function round;
|
||||
use function spl_object_hash;
|
||||
use function sprintf;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use const JSON_PRETTY_PRINT;
|
||||
use const JSON_THROW_ON_ERROR;
|
||||
use const JSON_UNESCAPED_SLASHES;
|
||||
use const SORT_NUMERIC;
|
||||
|
||||
class MemoryManager{
|
||||
private const DEFAULT_CHECK_RATE = Server::TARGET_TICKS_PER_SECOND;
|
||||
private const DEFAULT_CONTINUOUS_TRIGGER_RATE = Server::TARGET_TICKS_PER_SECOND * 2;
|
||||
private const DEFAULT_TICKS_PER_GC = 30 * 60 * Server::TARGET_TICKS_PER_SECOND;
|
||||
|
||||
private int $memoryLimit;
|
||||
private int $globalMemoryLimit;
|
||||
private int $checkRate;
|
||||
private int $checkTicker = 0;
|
||||
private bool $lowMemory = false;
|
||||
|
||||
private bool $continuousTrigger = true;
|
||||
private int $continuousTriggerRate;
|
||||
private int $continuousTriggerCount = 0;
|
||||
private int $continuousTriggerTicker = 0;
|
||||
|
||||
private int $garbageCollectionPeriod;
|
||||
private int $garbageCollectionTicker = 0;
|
||||
private bool $garbageCollectionTrigger;
|
||||
private bool $garbageCollectionAsync;
|
||||
|
||||
private int $lowMemChunkRadiusOverride;
|
||||
private bool $lowMemChunkGC;
|
||||
|
||||
private bool $lowMemDisableChunkCache;
|
||||
private bool $lowMemClearWorldCache;
|
||||
|
||||
private bool $dumpWorkers = true;
|
||||
|
||||
private \Logger $logger;
|
||||
|
||||
public function __construct(
|
||||
private Server $server
|
||||
){
|
||||
$this->logger = new \PrefixedLogger($server->getLogger(), "Memory Manager");
|
||||
|
||||
$this->init($server->getConfigGroup());
|
||||
}
|
||||
|
||||
private function init(ServerConfigGroup $config) : void{
|
||||
$this->memoryLimit = $config->getPropertyInt("memory.main-limit", 0) * 1024 * 1024;
|
||||
|
||||
$defaultMemory = 1024;
|
||||
|
||||
if(preg_match("/([0-9]+)([KMGkmg])/", $config->getConfigString("memory-limit", ""), $matches) > 0){
|
||||
$m = (int) $matches[1];
|
||||
if($m <= 0){
|
||||
$defaultMemory = 0;
|
||||
}else{
|
||||
$defaultMemory = match(mb_strtoupper($matches[2])){
|
||||
"K" => intdiv($m, 1024),
|
||||
"M" => $m,
|
||||
"G" => $m * 1024,
|
||||
default => $m,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
$hardLimit = $config->getPropertyInt("memory.main-hard-limit", $defaultMemory);
|
||||
|
||||
if($hardLimit <= 0){
|
||||
ini_set("memory_limit", '-1');
|
||||
}else{
|
||||
ini_set("memory_limit", $hardLimit . "M");
|
||||
}
|
||||
|
||||
$this->globalMemoryLimit = $config->getPropertyInt("memory.global-limit", 0) * 1024 * 1024;
|
||||
$this->checkRate = $config->getPropertyInt("memory.check-rate", self::DEFAULT_CHECK_RATE);
|
||||
$this->continuousTrigger = $config->getPropertyBool("memory.continuous-trigger", true);
|
||||
$this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", self::DEFAULT_CONTINUOUS_TRIGGER_RATE);
|
||||
|
||||
$this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", self::DEFAULT_TICKS_PER_GC);
|
||||
$this->garbageCollectionTrigger = $config->getPropertyBool("memory.garbage-collection.low-memory-trigger", true);
|
||||
$this->garbageCollectionAsync = $config->getPropertyBool("memory.garbage-collection.collect-async-worker", true);
|
||||
|
||||
$this->lowMemChunkRadiusOverride = $config->getPropertyInt("memory.max-chunks.chunk-radius", 4);
|
||||
$this->lowMemChunkGC = $config->getPropertyBool("memory.max-chunks.trigger-chunk-collect", true);
|
||||
|
||||
$this->lowMemDisableChunkCache = $config->getPropertyBool("memory.world-caches.disable-chunk-cache", true);
|
||||
$this->lowMemClearWorldCache = $config->getPropertyBool("memory.world-caches.low-memory-trigger", true);
|
||||
|
||||
$this->dumpWorkers = $config->getPropertyBool("memory.memory-dump.dump-async-worker", true);
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
public function isLowMemory() : bool{
|
||||
return $this->lowMemory;
|
||||
}
|
||||
|
||||
public function getGlobalMemoryLimit() : int{
|
||||
return $this->globalMemoryLimit;
|
||||
}
|
||||
|
||||
public function canUseChunkCache() : bool{
|
||||
return !$this->lowMemory || !$this->lowMemDisableChunkCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the allowed chunk radius based on the current memory usage.
|
||||
*/
|
||||
public function getViewDistance(int $distance) : int{
|
||||
return ($this->lowMemory && $this->lowMemChunkRadiusOverride > 0) ? min($this->lowMemChunkRadiusOverride, $distance) : $distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers garbage collection and cache cleanup to try and free memory.
|
||||
*/
|
||||
public function trigger(int $memory, int $limit, bool $global = false, int $triggerCount = 0) : void{
|
||||
$this->logger->debug(sprintf("%sLow memory triggered, limit %gMB, using %gMB",
|
||||
$global ? "Global " : "", round(($limit / 1024) / 1024, 2), round(($memory / 1024) / 1024, 2)));
|
||||
if($this->lowMemClearWorldCache){
|
||||
foreach($this->server->getWorldManager()->getWorlds() as $world){
|
||||
$world->clearCache(true);
|
||||
}
|
||||
ChunkCache::pruneCaches();
|
||||
}
|
||||
|
||||
if($this->lowMemChunkGC){
|
||||
foreach($this->server->getWorldManager()->getWorlds() as $world){
|
||||
$world->doChunkGarbageCollection();
|
||||
}
|
||||
}
|
||||
|
||||
$ev = new LowMemoryEvent($memory, $limit, $global, $triggerCount);
|
||||
$ev->call();
|
||||
|
||||
$cycles = 0;
|
||||
if($this->garbageCollectionTrigger){
|
||||
$cycles = $this->triggerGarbageCollector();
|
||||
}
|
||||
|
||||
$this->logger->debug(sprintf("Freed %gMB, $cycles cycles", round(($ev->getMemoryFreed() / 1024) / 1024, 2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick to update the memory manager state.
|
||||
*/
|
||||
public function check() : void{
|
||||
Timings::$memoryManager->startTiming();
|
||||
|
||||
if(($this->memoryLimit > 0 || $this->globalMemoryLimit > 0) && ++$this->checkTicker >= $this->checkRate){
|
||||
$this->checkTicker = 0;
|
||||
$memory = Process::getAdvancedMemoryUsage();
|
||||
$trigger = false;
|
||||
if($this->memoryLimit > 0 && $memory[0] > $this->memoryLimit){
|
||||
$trigger = 0;
|
||||
}elseif($this->globalMemoryLimit > 0 && $memory[1] > $this->globalMemoryLimit){
|
||||
$trigger = 1;
|
||||
}
|
||||
|
||||
if($trigger !== false){
|
||||
if($this->lowMemory && $this->continuousTrigger){
|
||||
if(++$this->continuousTriggerTicker >= $this->continuousTriggerRate){
|
||||
$this->continuousTriggerTicker = 0;
|
||||
$this->trigger($memory[$trigger], $this->memoryLimit, $trigger > 0, ++$this->continuousTriggerCount);
|
||||
}
|
||||
}else{
|
||||
$this->lowMemory = true;
|
||||
$this->continuousTriggerCount = 0;
|
||||
$this->trigger($memory[$trigger], $this->memoryLimit, $trigger > 0);
|
||||
}
|
||||
}else{
|
||||
$this->lowMemory = false;
|
||||
}
|
||||
}
|
||||
|
||||
if($this->garbageCollectionPeriod > 0 && ++$this->garbageCollectionTicker >= $this->garbageCollectionPeriod){
|
||||
$this->garbageCollectionTicker = 0;
|
||||
$this->triggerGarbageCollector();
|
||||
}
|
||||
|
||||
Timings::$memoryManager->stopTiming();
|
||||
}
|
||||
|
||||
public function triggerGarbageCollector() : int{
|
||||
Timings::$garbageCollector->startTiming();
|
||||
|
||||
if($this->garbageCollectionAsync){
|
||||
$pool = $this->server->getAsyncPool();
|
||||
if(($w = $pool->shutdownUnusedWorkers()) > 0){
|
||||
$this->logger->debug("Shut down $w idle async pool workers");
|
||||
}
|
||||
foreach($pool->getRunningWorkers() as $i){
|
||||
$pool->submitTaskToWorker(new GarbageCollectionTask(), $i);
|
||||
}
|
||||
}
|
||||
|
||||
$cycles = gc_collect_cycles();
|
||||
gc_mem_caches();
|
||||
|
||||
Timings::$garbageCollector->stopTiming();
|
||||
|
||||
return $cycles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the server memory into the specified output folder.
|
||||
*/
|
||||
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize) : void{
|
||||
$logger = new \PrefixedLogger($this->server->getLogger(), "Memory Dump");
|
||||
$logger->notice("After the memory dump is done, the server might crash");
|
||||
self::dumpMemory($this->server, $outputFolder, $maxNesting, $maxStringSize, $logger);
|
||||
|
||||
if($this->dumpWorkers){
|
||||
$pool = $this->server->getAsyncPool();
|
||||
foreach($pool->getRunningWorkers() as $i){
|
||||
$pool->submitTaskToWorker(new DumpWorkerMemoryTask($outputFolder, $maxNesting, $maxStringSize), $i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Static memory dumper accessible from any thread.
|
||||
*/
|
||||
public static function dumpMemory(mixed $startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{
|
||||
$hardLimit = Utils::assumeNotFalse(ini_get('memory_limit'), "memory_limit INI directive should always exist");
|
||||
ini_set('memory_limit', '-1');
|
||||
gc_disable();
|
||||
|
||||
if(!file_exists($outputFolder)){
|
||||
mkdir($outputFolder, 0777, true);
|
||||
}
|
||||
|
||||
$obData = Utils::assumeNotFalse(fopen(Path::join($outputFolder, "objects.js"), "wb+"));
|
||||
|
||||
$objects = [];
|
||||
|
||||
$refCounts = [];
|
||||
|
||||
$instanceCounts = [];
|
||||
|
||||
$staticProperties = [];
|
||||
$staticCount = 0;
|
||||
|
||||
$functionStaticVars = [];
|
||||
$functionStaticVarsCount = 0;
|
||||
|
||||
foreach(get_declared_classes() as $className){
|
||||
$reflection = new \ReflectionClass($className);
|
||||
$staticProperties[$className] = [];
|
||||
foreach($reflection->getProperties() as $property){
|
||||
if(!$property->isStatic() || $property->getDeclaringClass()->getName() !== $className){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!$property->isInitialized()){
|
||||
continue;
|
||||
}
|
||||
|
||||
$staticCount++;
|
||||
$staticProperties[$className][$property->getName()] = self::continueDump($property->getValue(), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
if(count($staticProperties[$className]) === 0){
|
||||
unset($staticProperties[$className]);
|
||||
}
|
||||
|
||||
foreach($reflection->getMethods() as $method){
|
||||
if($method->getDeclaringClass()->getName() !== $reflection->getName()){
|
||||
continue;
|
||||
}
|
||||
$methodStatics = [];
|
||||
foreach($method->getStaticVariables() as $name => $variable){
|
||||
$methodStatics[$name] = self::continueDump($variable, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
if(count($methodStatics) > 0){
|
||||
$functionStaticVars[$className . "::" . $method->getName()] = $methodStatics;
|
||||
$functionStaticVarsCount += count($functionStaticVars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents(Path::join($outputFolder, "staticProperties.js"), json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||
$logger->info("Wrote $staticCount static properties");
|
||||
|
||||
$globalVariables = [];
|
||||
$globalCount = 0;
|
||||
|
||||
$ignoredGlobals = [
|
||||
'GLOBALS' => true,
|
||||
'_SERVER' => true,
|
||||
'_REQUEST' => true,
|
||||
'_POST' => true,
|
||||
'_GET' => true,
|
||||
'_FILES' => true,
|
||||
'_ENV' => true,
|
||||
'_COOKIE' => true,
|
||||
'_SESSION' => true
|
||||
];
|
||||
|
||||
foreach(Utils::stringifyKeys($GLOBALS) as $varName => $value){
|
||||
if(isset($ignoredGlobals[$varName])){
|
||||
continue;
|
||||
}
|
||||
|
||||
$globalCount++;
|
||||
$globalVariables[$varName] = self::continueDump($value, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
file_put_contents(Path::join($outputFolder, "globalVariables.js"), json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||
$logger->info("Wrote $globalCount global variables");
|
||||
|
||||
foreach(get_defined_functions()["user"] as $function){
|
||||
$reflect = new \ReflectionFunction($function);
|
||||
|
||||
$vars = [];
|
||||
foreach($reflect->getStaticVariables() as $varName => $variable){
|
||||
$vars[$varName] = self::continueDump($variable, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
if(count($vars) > 0){
|
||||
$functionStaticVars[$function] = $vars;
|
||||
$functionStaticVarsCount += count($vars);
|
||||
}
|
||||
}
|
||||
file_put_contents(Path::join($outputFolder, 'functionStaticVars.js'), json_encode($functionStaticVars, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||
$logger->info("Wrote $functionStaticVarsCount function static variables");
|
||||
|
||||
$data = self::continueDump($startingObject, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
|
||||
do{
|
||||
$continue = false;
|
||||
foreach(Utils::stringifyKeys($objects) as $hash => $object){
|
||||
if(!is_object($object)){
|
||||
continue;
|
||||
}
|
||||
$continue = true;
|
||||
|
||||
$className = get_class($object);
|
||||
if(!isset($instanceCounts[$className])){
|
||||
$instanceCounts[$className] = 1;
|
||||
}else{
|
||||
$instanceCounts[$className]++;
|
||||
}
|
||||
|
||||
$objects[$hash] = true;
|
||||
$info = [
|
||||
"information" => "$hash@$className",
|
||||
];
|
||||
if($object instanceof \Closure){
|
||||
$info["definition"] = Utils::getNiceClosureName($object);
|
||||
$info["referencedVars"] = [];
|
||||
$reflect = new \ReflectionFunction($object);
|
||||
if(($closureThis = $reflect->getClosureThis()) !== null){
|
||||
$info["this"] = self::continueDump($closureThis, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
foreach($reflect->getStaticVariables() as $name => $variable){
|
||||
$info["referencedVars"][$name] = self::continueDump($variable, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
}else{
|
||||
$reflection = new \ReflectionObject($object);
|
||||
|
||||
$info["properties"] = [];
|
||||
|
||||
for($original = $reflection; $reflection !== false; $reflection = $reflection->getParentClass()){
|
||||
foreach($reflection->getProperties() as $property){
|
||||
if($property->isStatic()){
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = $property->getName();
|
||||
if($reflection !== $original){
|
||||
if($property->isPrivate()){
|
||||
$name = $reflection->getName() . ":" . $name;
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(!$property->isInitialized($object)){
|
||||
continue;
|
||||
}
|
||||
|
||||
$info["properties"][$name] = self::continueDump($property->getValue($object), $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fwrite($obData, json_encode($info, JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n");
|
||||
}
|
||||
|
||||
}while($continue);
|
||||
|
||||
$logger->info("Wrote " . count($objects) . " objects");
|
||||
|
||||
fclose($obData);
|
||||
|
||||
file_put_contents(Path::join($outputFolder, "serverEntry.js"), json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||
file_put_contents(Path::join($outputFolder, "referenceCounts.js"), json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||
|
||||
arsort($instanceCounts, SORT_NUMERIC);
|
||||
file_put_contents(Path::join($outputFolder, "instanceCounts.js"), json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
||||
|
||||
$logger->info("Finished!");
|
||||
|
||||
ini_set('memory_limit', $hardLimit);
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object[] $objects reference parameter
|
||||
* @param int[] $refCounts reference parameter
|
||||
*
|
||||
* @phpstan-param array<string, object> $objects
|
||||
* @phpstan-param array<string, int> $refCounts
|
||||
* @phpstan-param-out array<string, object> $objects
|
||||
* @phpstan-param-out array<string, int> $refCounts
|
||||
*/
|
||||
private static function continueDump(mixed $from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize) : mixed{
|
||||
if($maxNesting <= 0){
|
||||
return "(error) NESTING LIMIT REACHED";
|
||||
}
|
||||
|
||||
--$maxNesting;
|
||||
|
||||
if(is_object($from)){
|
||||
if(!isset($objects[$hash = spl_object_hash($from)])){
|
||||
$objects[$hash] = $from;
|
||||
$refCounts[$hash] = 0;
|
||||
}
|
||||
|
||||
++$refCounts[$hash];
|
||||
|
||||
$data = "(object) $hash";
|
||||
}elseif(is_array($from)){
|
||||
if($recursion >= 5){
|
||||
return "(error) ARRAY RECURSION LIMIT REACHED";
|
||||
}
|
||||
$data = [];
|
||||
$numeric = 0;
|
||||
foreach($from as $key => $value){
|
||||
$data[$numeric] = [
|
||||
"k" => self::continueDump($key, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize),
|
||||
"v" => self::continueDump($value, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize),
|
||||
];
|
||||
$numeric++;
|
||||
}
|
||||
}elseif(is_string($from)){
|
||||
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
|
||||
}elseif(is_resource($from)){
|
||||
$data = "(resource) " . print_r($from, true);
|
||||
}elseif(is_float($from)){
|
||||
$data = "(float) $from";
|
||||
}else{
|
||||
$data = $from;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -1,358 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine {
|
||||
|
||||
use Composer\InstalledVersions;
|
||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||
use pocketmine\thread\ThreadManager;
|
||||
use pocketmine\thread\ThreadSafeClassLoader;
|
||||
use pocketmine\utils\Filesystem;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\ServerKiller;
|
||||
use pocketmine\utils\Terminal;
|
||||
use pocketmine\utils\Timezone;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\wizard\SetupWizard;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function defined;
|
||||
use function extension_loaded;
|
||||
use function function_exists;
|
||||
use function getcwd;
|
||||
use function is_dir;
|
||||
use function mkdir;
|
||||
use function phpversion;
|
||||
use function preg_match;
|
||||
use function preg_quote;
|
||||
use function realpath;
|
||||
use function version_compare;
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
require_once __DIR__ . '/VersionInfo.php';
|
||||
|
||||
const MIN_PHP_VERSION = "8.1.0";
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
function critical_error($message){
|
||||
echo "[ERROR] $message" . PHP_EOL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Startup code. Do not look at it, it may harm you.
|
||||
* This is the only non-class based file on this project.
|
||||
* Enjoy it as much as I did writing it. I don't want to do it again.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
function check_platform_dependencies(){
|
||||
if(version_compare(MIN_PHP_VERSION, PHP_VERSION) > 0){
|
||||
//If PHP version isn't high enough, anything below might break, so don't bother checking it.
|
||||
return [
|
||||
"PHP >= " . MIN_PHP_VERSION . " is required, but you have PHP " . PHP_VERSION . "."
|
||||
];
|
||||
}
|
||||
|
||||
$messages = [];
|
||||
|
||||
if(PHP_INT_SIZE < 8){
|
||||
$messages[] = "32-bit systems/PHP are no longer supported. Please upgrade to a 64-bit system, or use a 64-bit PHP binary if this is a 64-bit system.";
|
||||
}
|
||||
|
||||
if(php_sapi_name() !== "cli"){
|
||||
$messages[] = "Only PHP CLI is supported.";
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
"chunkutils2" => "PocketMine ChunkUtils v2",
|
||||
"curl" => "cURL",
|
||||
"crypto" => "php-crypto",
|
||||
"ctype" => "ctype",
|
||||
"date" => "Date",
|
||||
"gmp" => "GMP",
|
||||
"hash" => "Hash",
|
||||
"igbinary" => "igbinary",
|
||||
"json" => "JSON",
|
||||
"leveldb" => "LevelDB",
|
||||
"mbstring" => "Multibyte String",
|
||||
"morton" => "morton",
|
||||
"openssl" => "OpenSSL",
|
||||
"pcre" => "PCRE",
|
||||
"phar" => "Phar",
|
||||
"pmmpthread" => "pmmpthread",
|
||||
"reflection" => "Reflection",
|
||||
"sockets" => "Sockets",
|
||||
"spl" => "SPL",
|
||||
"yaml" => "YAML",
|
||||
"zip" => "Zip",
|
||||
"zlib" => "Zlib"
|
||||
];
|
||||
|
||||
foreach($extensions as $ext => $name){
|
||||
if(!extension_loaded($ext)){
|
||||
$messages[] = "Unable to find the $name ($ext) extension.";
|
||||
}
|
||||
}
|
||||
|
||||
if(($pmmpthread_version = phpversion("pmmpthread")) !== false){
|
||||
if(version_compare($pmmpthread_version, "6.0.1") < 0 || version_compare($pmmpthread_version, "7.0.0") >= 0){
|
||||
$messages[] = "pmmpthread ^6.0.1 is required, while you have $pmmpthread_version.";
|
||||
}
|
||||
}
|
||||
|
||||
if(($leveldb_version = phpversion("leveldb")) !== false){
|
||||
if(version_compare($leveldb_version, "0.2.1") < 0){
|
||||
$messages[] = "php-leveldb >= 0.2.1 is required, while you have $leveldb_version.";
|
||||
}
|
||||
if(!defined('LEVELDB_ZLIB_RAW_COMPRESSION')){
|
||||
$messages[] = "Given version of php-leveldb doesn't support ZLIB_RAW compression (use https://github.com/pmmp/php-leveldb)";
|
||||
}
|
||||
}
|
||||
|
||||
$chunkutils2_version = phpversion("chunkutils2");
|
||||
$wantedVersionLock = "0.3";
|
||||
$wantedVersionMin = "$wantedVersionLock.0";
|
||||
if($chunkutils2_version !== false && (
|
||||
version_compare($chunkutils2_version, $wantedVersionMin) < 0 ||
|
||||
preg_match("/^" . preg_quote($wantedVersionLock, "/") . "\.\d+(?:-dev)?$/", $chunkutils2_version) === 0 //lock in at ^0.2, optionally at a patch release
|
||||
)){
|
||||
$messages[] = "chunkutils2 ^$wantedVersionMin is required, while you have $chunkutils2_version.";
|
||||
}
|
||||
|
||||
if(extension_loaded("pocketmine")){
|
||||
$messages[] = "The native PocketMine extension is no longer supported.";
|
||||
}
|
||||
|
||||
if(!defined('AF_INET6')){
|
||||
$messages[] = "IPv6 support is required, but your PHP binary was built without IPv6 support.";
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
function emit_performance_warnings(\Logger $logger){
|
||||
if(PHP_DEBUG !== 0){
|
||||
$logger->warning("This PHP binary was compiled in debug mode. This has a major impact on performance.");
|
||||
}
|
||||
if(extension_loaded("xdebug") && (!function_exists('xdebug_info') || count(xdebug_info('mode')) !== 0)){
|
||||
$logger->warning("Xdebug extension is enabled. This has a major impact on performance.");
|
||||
}
|
||||
if(((int) ini_get('zend.assertions')) !== -1){
|
||||
$logger->warning("Debugging assertions are enabled. This may degrade performance. To disable them, set `zend.assertions = -1` in php.ini.");
|
||||
}
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged installation detected. This will degrade autoloading speed and make startup times longer.");
|
||||
}
|
||||
if(function_exists('opcache_get_status') && ($opcacheStatus = opcache_get_status(false)) !== false){
|
||||
$jitEnabled = $opcacheStatus["jit"]["on"] ?? false;
|
||||
if($jitEnabled !== false){
|
||||
$logger->warning(<<<'JIT_WARNING'
|
||||
|
||||
|
||||
--------------------------------------- ! WARNING ! ---------------------------------------
|
||||
You're using PHP with JIT enabled. This provides significant performance improvements.
|
||||
HOWEVER, it is EXPERIMENTAL, and has already been seen to cause weird and unexpected bugs.
|
||||
Proceed with caution.
|
||||
If you want to report any bugs, make sure to mention that you have enabled PHP JIT.
|
||||
To turn off JIT, change `opcache.jit` to `0` in your php.ini file.
|
||||
-------------------------------------------------------------------------------------------
|
||||
|
||||
JIT_WARNING
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
function set_ini_entries(){
|
||||
ini_set("allow_url_fopen", '1');
|
||||
ini_set("display_errors", '1');
|
||||
ini_set("display_startup_errors", '1');
|
||||
ini_set("default_charset", "utf-8");
|
||||
ini_set('assert.exception', '1');
|
||||
}
|
||||
|
||||
function getopt_string(string $opt) : ?string{
|
||||
$opts = getopt("", ["$opt:"]);
|
||||
if(isset($opts[$opt])){
|
||||
if(is_string($opts[$opt])){
|
||||
return $opts[$opt];
|
||||
}
|
||||
if(is_array($opts[$opt])){
|
||||
critical_error("Cannot specify --$opt multiple times");
|
||||
}else{
|
||||
critical_error("Missing value for --$opt");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
function server(){
|
||||
if(count($messages = check_platform_dependencies()) > 0){
|
||||
echo PHP_EOL;
|
||||
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
||||
critical_error("Selected PHP binary does not satisfy some requirements.");
|
||||
foreach($messages as $m){
|
||||
echo " - $m" . PHP_EOL;
|
||||
}
|
||||
critical_error("PHP binary used: " . $binary);
|
||||
critical_error("Loaded php.ini: " . (($file = php_ini_loaded_file()) !== false ? $file : "none"));
|
||||
$phprc = getenv("PHPRC");
|
||||
critical_error("Value of PHPRC environment variable: " . ($phprc === false ? "" : $phprc));
|
||||
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
|
||||
echo PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
unset($messages);
|
||||
|
||||
error_reporting(-1);
|
||||
set_ini_entries();
|
||||
|
||||
$bootstrap = dirname(__FILE__, 2) . '/vendor/autoload.php';
|
||||
if(!is_file($bootstrap)){
|
||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||
exit(1);
|
||||
}
|
||||
require_once($bootstrap);
|
||||
|
||||
$composerGitHash = InstalledVersions::getReference('pocketmine/pocketmine-mp');
|
||||
if($composerGitHash !== null){
|
||||
//we can't verify dependency versions if we were installed without using git
|
||||
$currentGitHash = explode("-", VersionInfo::GIT_HASH())[0];
|
||||
if($currentGitHash !== $composerGitHash){
|
||||
critical_error("Composer dependencies and/or autoloader are out of sync.");
|
||||
critical_error("- Current revision is $currentGitHash");
|
||||
critical_error("- Composer dependencies were last synchronized for revision $composerGitHash");
|
||||
critical_error("Out-of-sync Composer dependencies may result in crashes and classes not being found.");
|
||||
critical_error("Please synchronize Composer dependencies before running the server.");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ErrorToExceptionHandler::set();
|
||||
|
||||
$cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
|
||||
$dataPath = getopt_string("data") ?? $cwd;
|
||||
$pluginPath = getopt_string("plugins") ?? $cwd . DIRECTORY_SEPARATOR . "plugins";
|
||||
Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
|
||||
|
||||
if(!@mkdir($dataPath, 0777, true) && !is_dir($dataPath)){
|
||||
critical_error("Unable to create/access data directory at $dataPath. Check that the target location is accessible by the current user.");
|
||||
exit(1);
|
||||
}
|
||||
//this has to be done after we're sure the data path exists
|
||||
$dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
|
||||
|
||||
$lockFilePath = Path::join($dataPath, 'server.lock');
|
||||
try{
|
||||
$pid = Filesystem::createLockFile($lockFilePath);
|
||||
}catch(\InvalidArgumentException $e){
|
||||
critical_error($e->getMessage());
|
||||
critical_error("Please ensure that there is enough space on the disk and that the current user has read/write permissions to the selected data directory $dataPath.");
|
||||
exit(1);
|
||||
}
|
||||
if($pid !== null){
|
||||
critical_error("Another " . VersionInfo::NAME . " instance (PID $pid) is already using this folder (" . realpath($dataPath) . ").");
|
||||
critical_error("Please stop the other server first before running a new one.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(!@mkdir($pluginPath, 0777, true) && !is_dir($pluginPath)){
|
||||
critical_error("Unable to create plugin directory at $pluginPath. Check that the target location is accessible by the current user.");
|
||||
exit(1);
|
||||
}
|
||||
$pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
|
||||
|
||||
//Logger has a dependency on timezone
|
||||
Timezone::init();
|
||||
|
||||
$opts = getopt("", ["no-wizard", "enable-ansi", "disable-ansi"]);
|
||||
if(isset($opts["enable-ansi"])){
|
||||
Terminal::init(true);
|
||||
}elseif(isset($opts["disable-ansi"])){
|
||||
Terminal::init(false);
|
||||
}else{
|
||||
Terminal::init();
|
||||
}
|
||||
|
||||
$logger = new MainLogger(Path::join($dataPath, "server.log"), Terminal::hasFormattingCodes(), "Server", new \DateTimeZone(Timezone::get()));
|
||||
\GlobalLogger::set($logger);
|
||||
|
||||
emit_performance_warnings($logger);
|
||||
|
||||
$exitCode = 0;
|
||||
do{
|
||||
if(!file_exists(Path::join($dataPath, "server.properties")) && !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard($dataPath);
|
||||
if(!$installer->run()){
|
||||
$exitCode = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||
*/
|
||||
$autoloader = new ThreadSafeClassLoader();
|
||||
$autoloader->register(false);
|
||||
|
||||
new Server($autoloader, $logger, $dataPath, $pluginPath);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start();
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
|
||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||
$logger->debug("Some threads could not be stopped, performing a force-kill");
|
||||
Process::kill(Process::pid(), true);
|
||||
}
|
||||
}while(false);
|
||||
|
||||
$logger->shutdownLogWriterThread();
|
||||
|
||||
echo Terminal::$FORMAT_RESET . PHP_EOL;
|
||||
|
||||
Filesystem::releaseLockFile($lockFilePath);
|
||||
|
||||
exit($exitCode);
|
||||
}
|
||||
|
||||
\pocketmine\server();
|
||||
}
|
1856
src/Server.php
1856
src/Server.php
File diff suppressed because it is too large
Load Diff
@ -1,135 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\utils\Config;
|
||||
use function array_key_exists;
|
||||
use function getopt;
|
||||
use function is_bool;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
use function strtolower;
|
||||
|
||||
final class ServerConfigGroup{
|
||||
/**
|
||||
* @var mixed[]
|
||||
* @phpstan-var array<string, mixed>
|
||||
*/
|
||||
private array $propertyCache = [];
|
||||
|
||||
public function __construct(
|
||||
private Config $pocketmineYml,
|
||||
private Config $serverProperties
|
||||
){}
|
||||
|
||||
public function getProperty(string $variable, mixed $defaultValue = null) : mixed{
|
||||
if(!array_key_exists($variable, $this->propertyCache)){
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
$this->propertyCache[$variable] = $v[$variable];
|
||||
}else{
|
||||
$this->propertyCache[$variable] = $this->pocketmineYml->getNested($variable);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->propertyCache[$variable] ?? $defaultValue;
|
||||
}
|
||||
|
||||
public function getPropertyBool(string $variable, bool $defaultValue) : bool{
|
||||
return (bool) $this->getProperty($variable, $defaultValue);
|
||||
}
|
||||
|
||||
public function getPropertyInt(string $variable, int $defaultValue) : int{
|
||||
return (int) $this->getProperty($variable, $defaultValue);
|
||||
}
|
||||
|
||||
public function getPropertyString(string $variable, string $defaultValue) : string{
|
||||
return (string) $this->getProperty($variable, $defaultValue);
|
||||
}
|
||||
|
||||
public function getConfigString(string $variable, string $defaultValue = "") : string{
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
return (string) $v[$variable];
|
||||
}
|
||||
|
||||
return $this->serverProperties->exists($variable) ? (string) $this->serverProperties->get($variable) : $defaultValue;
|
||||
}
|
||||
|
||||
public function setConfigString(string $variable, string $value) : void{
|
||||
$this->serverProperties->set($variable, $value);
|
||||
}
|
||||
|
||||
public function getConfigInt(string $variable, int $defaultValue = 0) : int{
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
return (int) $v[$variable];
|
||||
}
|
||||
|
||||
return $this->serverProperties->exists($variable) ? (int) $this->serverProperties->get($variable) : $defaultValue;
|
||||
}
|
||||
|
||||
public function setConfigInt(string $variable, int $value) : void{
|
||||
$this->serverProperties->set($variable, $value);
|
||||
}
|
||||
|
||||
public function getConfigBool(string $variable, bool $defaultValue = false) : bool{
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
$value = $v[$variable];
|
||||
}else{
|
||||
$value = $this->serverProperties->exists($variable) ? $this->serverProperties->get($variable) : $defaultValue;
|
||||
}
|
||||
if(is_bool($value)){
|
||||
return $value;
|
||||
}
|
||||
if(is_int($value)){
|
||||
return $value !== 0;
|
||||
}
|
||||
if(is_string($value)){
|
||||
switch(strtolower($value)){
|
||||
case "on":
|
||||
case "true":
|
||||
case "1":
|
||||
case "yes":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setConfigBool(string $variable, bool $value) : void{
|
||||
$this->serverProperties->set($variable, $value ? "1" : "0");
|
||||
}
|
||||
|
||||
public function save() : void{
|
||||
if($this->serverProperties->hasChanged()){
|
||||
$this->serverProperties->save();
|
||||
}
|
||||
if($this->pocketmineYml->hasChanged()){
|
||||
$this->pocketmineYml->save();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\snooze\SleeperHandler;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use function hrtime;
|
||||
|
||||
/**
|
||||
* Custom Snooze sleeper handler which captures notification processing time.
|
||||
* @internal
|
||||
*/
|
||||
final class TimeTrackingSleeperHandler extends SleeperHandler{
|
||||
|
||||
private int $notificationProcessingTimeNs = 0;
|
||||
|
||||
public function __construct(
|
||||
private TimingsHandler $timings
|
||||
){
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time in nanoseconds spent processing notifications since the last reset.
|
||||
*/
|
||||
public function getNotificationProcessingTime() : int{ return $this->notificationProcessingTimeNs; }
|
||||
|
||||
/**
|
||||
* Resets the notification processing time tracker to zero.
|
||||
*/
|
||||
public function resetNotificationProcessingTime() : void{ $this->notificationProcessingTimeNs = 0; }
|
||||
|
||||
public function processNotifications() : void{
|
||||
$startTime = hrtime(true);
|
||||
$this->timings->startTiming();
|
||||
try{
|
||||
parent::processNotifications();
|
||||
}finally{
|
||||
$this->notificationProcessingTimeNs += hrtime(true) - $startTime;
|
||||
$this->timings->stopTiming();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\utils\Git;
|
||||
use pocketmine\utils\VersionString;
|
||||
use function is_array;
|
||||
use function is_int;
|
||||
use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "5.0.1";
|
||||
public const IS_DEVELOPMENT_BUILD = false;
|
||||
public const BUILD_CHANNEL = "stable";
|
||||
|
||||
/**
|
||||
* PocketMine-MP-specific version ID for world data. Used to determine what fixes need to be applied to old world
|
||||
* data (e.g. stuff saved wrongly by past versions).
|
||||
* This version supplements the Minecraft vanilla world version.
|
||||
*
|
||||
* This should be bumped if any **non-Mojang** BC-breaking change or bug fix is made to world save data of any kind
|
||||
* (entities, tiles, blocks, biomes etc.). For example, if PM accidentally saved a block with its facing value
|
||||
* swapped, we would bump this, but not if Mojang did the same change.
|
||||
*/
|
||||
public const WORLD_DATA_VERSION = 1;
|
||||
/**
|
||||
* Name of the NBT tag used to store the world data version.
|
||||
*/
|
||||
public const TAG_WORLD_DATA_VERSION = "PMMPDataVersion"; //TAG_Long
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
private static ?string $gitHash = null;
|
||||
|
||||
public static function GIT_HASH() : string{
|
||||
if(self::$gitHash === null){
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$gitHash = Git::getRepositoryStatePretty(\pocketmine\PATH);
|
||||
}else{
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(isset($meta["git"])){
|
||||
$gitHash = $meta["git"];
|
||||
}
|
||||
}
|
||||
|
||||
self::$gitHash = $gitHash;
|
||||
}
|
||||
|
||||
return self::$gitHash;
|
||||
}
|
||||
|
||||
private static ?int $buildNumber = null;
|
||||
|
||||
public static function BUILD_NUMBER() : int{
|
||||
if(self::$buildNumber === null){
|
||||
self::$buildNumber = 0;
|
||||
if(\Phar::running(true) !== ""){
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(is_array($meta) && isset($meta["build"]) && is_int($meta["build"])){
|
||||
self::$buildNumber = $meta["build"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self::$buildNumber;
|
||||
}
|
||||
|
||||
private static ?VersionString $fullVersion = null;
|
||||
|
||||
public static function VERSION() : VersionString{
|
||||
if(self::$fullVersion === null){
|
||||
self::$fullVersion = new VersionString(self::BASE_VERSION, self::IS_DEVELOPMENT_BUILD, self::BUILD_NUMBER());
|
||||
}
|
||||
return self::$fullVersion;
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
/**
|
||||
* Air block
|
||||
*/
|
||||
class Air extends Flowable{
|
||||
|
||||
public function canBeReplaced() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function canBePlaced() : bool{
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\inventory\AnvilInventory;
|
||||
use pocketmine\block\utils\Fallable;
|
||||
use pocketmine\block\utils\FallableTrait;
|
||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\entity\object\FallingBlock;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\AnvilFallSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use function lcg_value;
|
||||
use function round;
|
||||
|
||||
class Anvil extends Transparent implements Fallable{
|
||||
use FallableTrait;
|
||||
use HorizontalFacingTrait;
|
||||
|
||||
public const UNDAMAGED = 0;
|
||||
public const SLIGHTLY_DAMAGED = 1;
|
||||
public const VERY_DAMAGED = 2;
|
||||
|
||||
private int $damage = self::UNDAMAGED;
|
||||
|
||||
public function describeBlockItemState(RuntimeDataDescriber $w) : void{
|
||||
$w->boundedInt(2, self::UNDAMAGED, self::VERY_DAMAGED, $this->damage);
|
||||
}
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->horizontalFacing($this->facing);
|
||||
}
|
||||
|
||||
public function getDamage() : int{ return $this->damage; }
|
||||
|
||||
/** @return $this */
|
||||
public function setDamage(int $damage) : self{
|
||||
if($damage < self::UNDAMAGED || $damage > self::VERY_DAMAGED){
|
||||
throw new \InvalidArgumentException("Damage must be in range " . self::UNDAMAGED . " ... " . self::VERY_DAMAGED);
|
||||
}
|
||||
$this->damage = $damage;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
return [AxisAlignedBB::one()->squash(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8)];
|
||||
}
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
$player->setCurrentWindow(new AnvilInventory($this->position));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$this->facing = Facing::rotateY($player->getHorizontalFacing(), true);
|
||||
}
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onHitGround(FallingBlock $blockEntity) : bool{
|
||||
if(lcg_value() < 0.05 + (round($blockEntity->getFallDistance()) - 1) * 0.05){
|
||||
if($this->damage !== self::VERY_DAMAGED){
|
||||
$this->damage = $this->damage + 1;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFallDamagePerBlock() : float{
|
||||
return 2.0;
|
||||
}
|
||||
|
||||
public function getMaxFallDamage() : float{
|
||||
return 40.0;
|
||||
}
|
||||
|
||||
public function getLandSound() : ?Sound{
|
||||
return new AnvilFallSound();
|
||||
}
|
||||
}
|
@ -1,240 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\event\block\StructureGrowEvent;
|
||||
use pocketmine\item\Bamboo as ItemBamboo;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function count;
|
||||
use function gmp_add;
|
||||
use function gmp_and;
|
||||
use function gmp_intval;
|
||||
use function gmp_mul;
|
||||
use function gmp_xor;
|
||||
use function min;
|
||||
use function mt_rand;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
class Bamboo extends Transparent{
|
||||
|
||||
public const NO_LEAVES = 0;
|
||||
public const SMALL_LEAVES = 1;
|
||||
public const LARGE_LEAVES = 2;
|
||||
|
||||
protected bool $thick = false; //age in PC, but this is 0/1
|
||||
protected bool $ready = false;
|
||||
protected int $leafSize = self::NO_LEAVES;
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->boundedInt(2, self::NO_LEAVES, self::LARGE_LEAVES, $this->leafSize);
|
||||
$w->bool($this->thick);
|
||||
$w->bool($this->ready);
|
||||
}
|
||||
|
||||
public function isThick() : bool{ return $this->thick; }
|
||||
|
||||
/** @return $this */
|
||||
public function setThick(bool $thick) : self{
|
||||
$this->thick = $thick;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isReady() : bool{ return $this->ready; }
|
||||
|
||||
/** @return $this */
|
||||
public function setReady(bool $ready) : self{
|
||||
$this->ready = $ready;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLeafSize() : int{ return $this->leafSize; }
|
||||
|
||||
/** @return $this */
|
||||
public function setLeafSize(int $leafSize) : self{
|
||||
$this->leafSize = $leafSize;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
//this places the BB at the northwest corner, not the center
|
||||
$inset = 1 - (($this->thick ? 3 : 2) / 16);
|
||||
return [AxisAlignedBB::one()->trim(Facing::SOUTH, $inset)->trim(Facing::EAST, $inset)];
|
||||
}
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
private static function getOffsetSeed(int $x, int $y, int $z) : int{
|
||||
$p1 = gmp_mul($z, 0x6ebfff5);
|
||||
$p2 = gmp_mul($x, 0x2fc20f);
|
||||
$p3 = $y;
|
||||
|
||||
$xord = gmp_xor(gmp_xor($p1, $p2), $p3);
|
||||
|
||||
$fullResult = gmp_mul(gmp_add(gmp_mul($xord, 0x285b825), 0xb), $xord);
|
||||
return gmp_intval(gmp_and($fullResult, 0xffffffff));
|
||||
}
|
||||
|
||||
private static function getMaxHeight(int $x, int $z) : int{
|
||||
return 12 + (self::getOffsetSeed($x, 0, $z) % 5);
|
||||
}
|
||||
|
||||
public function getModelPositionOffset() : ?Vector3{
|
||||
$seed = self::getOffsetSeed($this->position->getFloorX(), 0, $this->position->getFloorZ());
|
||||
$retX = (($seed % 12) + 1) / 16;
|
||||
$retZ = ((($seed >> 8) % 12) + 1) / 16;
|
||||
return new Vector3($retX, 0, $retZ);
|
||||
}
|
||||
|
||||
private function canBeSupportedBy(Block $block) : bool{
|
||||
return
|
||||
$block->getTypeId() === BlockTypeIds::GRAVEL ||
|
||||
$block->hasTypeTag(BlockTypeTags::DIRT) ||
|
||||
$block->hasTypeTag(BlockTypeTags::MUD) ||
|
||||
$block->hasTypeTag(BlockTypeTags::SAND);
|
||||
}
|
||||
|
||||
private function seekToTop() : Bamboo{
|
||||
$world = $this->position->getWorld();
|
||||
$top = $this;
|
||||
while(($next = $world->getBlock($top->position->up())) instanceof Bamboo && $next->hasSameTypeId($this)){
|
||||
$top = $next;
|
||||
}
|
||||
return $top;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item instanceof Fertilizer){
|
||||
$top = $this->seekToTop();
|
||||
if($top->grow(self::getMaxHeight($top->position->getFloorX(), $top->position->getFloorZ()), mt_rand(1, 2), $player)){
|
||||
$item->pop();
|
||||
return true;
|
||||
}
|
||||
}elseif($item instanceof ItemBamboo){
|
||||
if($this->seekToTop()->grow(PHP_INT_MAX, 1, $player)){
|
||||
$item->pop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$world = $this->position->getWorld();
|
||||
$below = $world->getBlock($this->position->down());
|
||||
if(!$this->canBeSupportedBy($below) && !$below->hasSameTypeId($this)){
|
||||
$world->useBreakOn($this->position);
|
||||
}
|
||||
}
|
||||
|
||||
private function grow(int $maxHeight, int $growAmount, ?Player $player) : bool{
|
||||
$world = $this->position->getWorld();
|
||||
if(!$world->getBlock($this->position->up())->canBeReplaced()){
|
||||
return false;
|
||||
}
|
||||
|
||||
$height = 1;
|
||||
while($world->getBlock($this->position->subtract(0, $height, 0))->hasSameTypeId($this)){
|
||||
if(++$height >= $maxHeight){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$newHeight = $height + $growAmount;
|
||||
|
||||
$stemBlock = (clone $this)->setReady(false)->setLeafSize(self::NO_LEAVES);
|
||||
if($newHeight >= 4 && !$stemBlock->isThick()){ //don't change it to false if height is less, because it might have been chopped
|
||||
$stemBlock = $stemBlock->setThick(true);
|
||||
}
|
||||
$smallLeavesBlock = (clone $stemBlock)->setLeafSize(self::SMALL_LEAVES);
|
||||
$bigLeavesBlock = (clone $stemBlock)->setLeafSize(self::LARGE_LEAVES);
|
||||
|
||||
$newBlocks = [];
|
||||
if($newHeight === 2){
|
||||
$newBlocks[] = $smallLeavesBlock;
|
||||
}elseif($newHeight === 3){
|
||||
$newBlocks[] = $smallLeavesBlock;
|
||||
$newBlocks[] = $smallLeavesBlock;
|
||||
}elseif($newHeight === 4){
|
||||
$newBlocks[] = $bigLeavesBlock;
|
||||
$newBlocks[] = $smallLeavesBlock;
|
||||
$newBlocks[] = $stemBlock;
|
||||
$newBlocks[] = $stemBlock;
|
||||
}elseif($newHeight > 4){
|
||||
$newBlocks[] = $bigLeavesBlock;
|
||||
$newBlocks[] = $bigLeavesBlock;
|
||||
$newBlocks[] = $smallLeavesBlock;
|
||||
for($i = 0, $max = min($growAmount, $newHeight - count($newBlocks)); $i < $max; ++$i){
|
||||
$newBlocks[] = $stemBlock; //to replace the bottom blocks that currently have leaves
|
||||
}
|
||||
}
|
||||
|
||||
$tx = new BlockTransaction($world);
|
||||
foreach($newBlocks as $idx => $newBlock){
|
||||
$tx->addBlock($this->position->subtract(0, $idx - $growAmount, 0), $newBlock);
|
||||
}
|
||||
|
||||
$ev = new StructureGrowEvent($this, $tx, $player);
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $tx->apply();
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
$world = $this->position->getWorld();
|
||||
if($this->ready){
|
||||
$this->ready = false;
|
||||
if($world->getFullLight($this->position) < 9 || !$this->grow(self::getMaxHeight($this->position->getFloorX(), $this->position->getFloorZ()), 1, null)){
|
||||
$world->setBlock($this->position, $this);
|
||||
}
|
||||
}elseif($world->getBlock($this->position->up())->canBeReplaced()){
|
||||
$this->ready = true;
|
||||
$world->setBlock($this->position, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaItems::BAMBOO();
|
||||
}
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\event\block\StructureGrowEvent;
|
||||
use pocketmine\item\Bamboo as ItemBamboo;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
final class BambooSapling extends Flowable{
|
||||
private bool $ready = false;
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->bool($this->ready);
|
||||
}
|
||||
|
||||
public function isReady() : bool{ return $this->ready; }
|
||||
|
||||
/** @return $this */
|
||||
public function setReady(bool $ready) : self{
|
||||
$this->ready = $ready;
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function canBeSupportedBy(Block $block) : bool{
|
||||
return
|
||||
$block->getTypeId() === BlockTypeIds::GRAVEL ||
|
||||
$block->hasTypeTag(BlockTypeTags::DIRT) ||
|
||||
$block->hasTypeTag(BlockTypeTags::MUD) ||
|
||||
$block->hasTypeTag(BlockTypeTags::SAND);
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if(!$this->canBeSupportedBy($blockReplace->position->getWorld()->getBlock($blockReplace->position->down()))){
|
||||
return false;
|
||||
}
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item instanceof Fertilizer || $item instanceof ItemBamboo){
|
||||
if($this->grow($player)){
|
||||
$item->pop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$world = $this->position->getWorld();
|
||||
if(!$this->canBeSupportedBy($world->getBlock($this->position->down()))){
|
||||
$world->useBreakOn($this->position);
|
||||
}
|
||||
}
|
||||
|
||||
private function grow(?Player $player) : bool{
|
||||
$world = $this->position->getWorld();
|
||||
if(!$world->getBlock($this->position->up())->canBeReplaced()){
|
||||
return false;
|
||||
}
|
||||
|
||||
$tx = new BlockTransaction($world);
|
||||
$bamboo = VanillaBlocks::BAMBOO();
|
||||
$tx->addBlock($this->position, $bamboo)
|
||||
->addBlock($this->position->up(), (clone $bamboo)->setLeafSize(Bamboo::SMALL_LEAVES));
|
||||
|
||||
$ev = new StructureGrowEvent($this, $tx, $player);
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $tx->apply();
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
$world = $this->position->getWorld();
|
||||
if($this->ready){
|
||||
$this->ready = false;
|
||||
if($world->getFullLight($this->position) < 9 || !$this->grow(null)){
|
||||
$world->setBlock($this->position, $this);
|
||||
}
|
||||
}elseif($world->getBlock($this->position->up())->canBeReplaced()){
|
||||
$this->ready = true;
|
||||
$world->setBlock($this->position, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaItems::BAMBOO();
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Barrel as TileBarrel;
|
||||
use pocketmine\block\utils\AnyFacingTrait;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function abs;
|
||||
|
||||
class Barrel extends Opaque{
|
||||
use AnyFacingTrait;
|
||||
|
||||
protected bool $open = false;
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->facing($this->facing);
|
||||
$w->bool($this->open);
|
||||
}
|
||||
|
||||
public function isOpen() : bool{
|
||||
return $this->open;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function setOpen(bool $open) : Barrel{
|
||||
$this->open = $open;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
if(abs($player->getPosition()->getX() - $this->position->getX()) < 2 && abs($player->getPosition()->getZ() - $this->position->getZ()) < 2){
|
||||
$y = $player->getEyePos()->getY();
|
||||
|
||||
if($y - $this->position->getY() > 2){
|
||||
$this->facing = Facing::UP;
|
||||
}elseif($this->position->getY() - $y > 0){
|
||||
$this->facing = Facing::DOWN;
|
||||
}else{
|
||||
$this->facing = Facing::opposite($player->getHorizontalFacing());
|
||||
}
|
||||
}else{
|
||||
$this->facing = Facing::opposite($player->getHorizontalFacing());
|
||||
}
|
||||
}
|
||||
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
$barrel = $this->position->getWorld()->getTile($this->position);
|
||||
if($barrel instanceof TileBarrel){
|
||||
if(!$barrel->canOpenWith($item->getCustomName())){
|
||||
return true;
|
||||
}
|
||||
|
||||
$player->setCurrentWindow($barrel->getInventory());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Banner as TileBanner;
|
||||
use pocketmine\block\utils\BannerPatternLayer;
|
||||
use pocketmine\block\utils\ColoredTrait;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\item\Banner as ItemBanner;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function array_filter;
|
||||
use function assert;
|
||||
use function count;
|
||||
|
||||
abstract class BaseBanner extends Transparent{
|
||||
use ColoredTrait;
|
||||
|
||||
/**
|
||||
* @var BannerPatternLayer[]
|
||||
* @phpstan-var list<BannerPatternLayer>
|
||||
*/
|
||||
protected array $patterns = [];
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||
$this->color = DyeColor::BLACK();
|
||||
parent::__construct($idInfo, $name, $typeInfo);
|
||||
}
|
||||
|
||||
public function readStateFromWorld() : Block{
|
||||
parent::readStateFromWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
if($tile instanceof TileBanner){
|
||||
$this->color = $tile->getBaseColor();
|
||||
$this->setPatterns($tile->getPatterns());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
assert($tile instanceof TileBanner);
|
||||
$tile->setBaseColor($this->color);
|
||||
$tile->setPatterns($this->patterns);
|
||||
}
|
||||
|
||||
public function isSolid() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getMaxStackSize() : int{
|
||||
return 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BannerPatternLayer[]
|
||||
* @phpstan-return list<BannerPatternLayer>
|
||||
*/
|
||||
public function getPatterns() : array{
|
||||
return $this->patterns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BannerPatternLayer[] $patterns
|
||||
*
|
||||
* @phpstan-param list<BannerPatternLayer> $patterns
|
||||
* @return $this
|
||||
*/
|
||||
public function setPatterns(array $patterns) : self{
|
||||
$checked = array_filter($patterns, fn($v) => $v instanceof BannerPatternLayer);
|
||||
if(count($checked) !== count($patterns)){
|
||||
throw new \TypeError("Deque must only contain " . BannerPatternLayer::class . " objects");
|
||||
}
|
||||
$this->patterns = $checked;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
private function canBeSupportedBy(Block $block) : bool{
|
||||
return $block->isSolid();
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if(!$this->canBeSupportedBy($blockReplace->getSide($this->getSupportingFace()))){
|
||||
return false;
|
||||
}
|
||||
if($item instanceof ItemBanner){
|
||||
$this->color = $item->getColor();
|
||||
$this->setPatterns($item->getPatterns());
|
||||
}
|
||||
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
abstract protected function getSupportingFace() : int;
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->canBeSupportedBy($this->getSide($this->getSupportingFace()))){
|
||||
$this->position->getWorld()->useBreakOn($this->position);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
$drop = $this->asItem();
|
||||
if($drop instanceof ItemBanner && count($this->patterns) > 0){
|
||||
$drop->setPatterns($this->patterns);
|
||||
}
|
||||
|
||||
return [$drop];
|
||||
}
|
||||
|
||||
public function getPickedItem(bool $addUserData = false) : Item{
|
||||
$result = $this->asItem();
|
||||
if($addUserData && $result instanceof ItemBanner && count($this->patterns) > 0){
|
||||
$result->setPatterns($this->patterns);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaItems::BANNER()->setColor($this->color);
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\entity\effect\EffectInstance;
|
||||
use pocketmine\entity\FoodSource;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
|
||||
abstract class BaseCake extends Transparent implements FoodSource{
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
if($down->getTypeId() !== BlockTypeIds::AIR){
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Facing::DOWN)->getTypeId() === BlockTypeIds::AIR){ //Replace with common break method
|
||||
$this->position->getWorld()->useBreakOn($this->position);
|
||||
}
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
return $player->consumeObject($this);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getFoodRestore() : int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getSaturationRestore() : float{
|
||||
return 0.4;
|
||||
}
|
||||
|
||||
public function requiresHunger() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EffectInstance[]
|
||||
*/
|
||||
public function getAdditionalEffects() : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
abstract public function getResidue() : Block;
|
||||
|
||||
public function onConsume(Living $consumer) : void{
|
||||
$this->position->getWorld()->setBlock($this->position, $this->getResidue());
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\CoralType;
|
||||
use pocketmine\block\utils\CoralTypeTrait;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\event\block\BlockDeathEvent;
|
||||
use pocketmine\item\Item;
|
||||
use function mt_rand;
|
||||
|
||||
abstract class BaseCoral extends Transparent{
|
||||
use CoralTypeTrait;
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||
$this->coralType = CoralType::TUBE();
|
||||
parent::__construct($idInfo, $name, $typeInfo);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->dead){
|
||||
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(40, 200));
|
||||
}
|
||||
}
|
||||
|
||||
public function onScheduledUpdate() : void{
|
||||
if(!$this->dead && !$this->isCoveredWithWater()){
|
||||
$ev = new BlockDeathEvent($this, $this->setDead(true));
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isSolid() : bool{ return false; }
|
||||
|
||||
protected function isCoveredWithWater() : bool{
|
||||
$world = $this->position->getWorld();
|
||||
|
||||
$hasWater = false;
|
||||
foreach($this->position->sides() as $vector3){
|
||||
if($world->getBlock($vector3) instanceof Water){
|
||||
$hasWater = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: check water inside the block itself (not supported on the API yet)
|
||||
return $hasWater;
|
||||
}
|
||||
|
||||
protected function recalculateCollisionBoxes() : array{ return []; }
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\projectile\Arrow;
|
||||
use pocketmine\event\entity\EntityCombustByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\item\Item;
|
||||
|
||||
abstract class BaseFire extends Flowable{
|
||||
|
||||
public function hasEntityCollision() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function canBeReplaced() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onEntityInside(Entity $entity) : bool{
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, $this->getFireDamage());
|
||||
$entity->attack($ev);
|
||||
|
||||
$ev = new EntityCombustByBlockEvent($this, $entity, 8);
|
||||
if($entity instanceof Arrow){
|
||||
$ev->cancel();
|
||||
}
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->setOnFire($ev->getDuration());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
abstract protected function getFireDamage() : int;
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\RailConnectionInfo;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function array_reverse;
|
||||
use function array_search;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function in_array;
|
||||
|
||||
abstract class BaseRail extends Flowable{
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($blockReplace->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onPostPlace() : void{
|
||||
$this->tryReconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $connections
|
||||
* @param int[][] $lookup
|
||||
* @phpstan-param array<int, list<int>> $lookup
|
||||
*/
|
||||
protected static function searchState(array $connections, array $lookup) : ?int{
|
||||
$shape = array_search($connections, $lookup, true);
|
||||
if($shape === false){
|
||||
$shape = array_search(array_reverse($connections), $lookup, true);
|
||||
}
|
||||
return $shape === false ? null : $shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the rail shape according to the given connections, if a shape matches.
|
||||
*
|
||||
* @param int[] $connections
|
||||
*
|
||||
* @throws \InvalidArgumentException if no shape matches the given connections
|
||||
*/
|
||||
abstract protected function setShapeFromConnections(array $connections) : void;
|
||||
|
||||
/**
|
||||
* Returns the connection directions of this rail (depending on the current block state)
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
abstract protected function getCurrentShapeConnections() : array;
|
||||
|
||||
/**
|
||||
* Returns all the directions this rail is already connected in.
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
private function getConnectedDirections() : array{
|
||||
/** @var int[] $connections */
|
||||
$connections = [];
|
||||
|
||||
/** @var int $connection */
|
||||
foreach($this->getCurrentShapeConnections() as $connection){
|
||||
$other = $this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND);
|
||||
$otherConnection = Facing::opposite($connection & ~RailConnectionInfo::FLAG_ASCEND);
|
||||
|
||||
if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0){
|
||||
$other = $other->getSide(Facing::UP);
|
||||
|
||||
}elseif(!($other instanceof BaseRail)){ //check for rail sloping up to meet this one
|
||||
$other = $other->getSide(Facing::DOWN);
|
||||
$otherConnection |= RailConnectionInfo::FLAG_ASCEND;
|
||||
}
|
||||
|
||||
if(
|
||||
$other instanceof BaseRail &&
|
||||
in_array($otherConnection, $other->getCurrentShapeConnections(), true)
|
||||
){
|
||||
$connections[] = $connection;
|
||||
}
|
||||
}
|
||||
|
||||
return $connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $constraints
|
||||
*
|
||||
* @return true[]
|
||||
* @phpstan-return array<int, true>
|
||||
*/
|
||||
private function getPossibleConnectionDirections(array $constraints) : array{
|
||||
switch(count($constraints)){
|
||||
case 0:
|
||||
//No constraints, can connect in any direction
|
||||
$possible = [
|
||||
Facing::NORTH => true,
|
||||
Facing::SOUTH => true,
|
||||
Facing::WEST => true,
|
||||
Facing::EAST => true
|
||||
];
|
||||
foreach($possible as $p => $_){
|
||||
$possible[$p | RailConnectionInfo::FLAG_ASCEND] = true;
|
||||
}
|
||||
|
||||
return $possible;
|
||||
case 1:
|
||||
return $this->getPossibleConnectionDirectionsOneConstraint(array_shift($constraints));
|
||||
case 2:
|
||||
return [];
|
||||
default:
|
||||
throw new \InvalidArgumentException("Expected at most 2 constraints, got " . count($constraints));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true[]
|
||||
* @phpstan-return array<int, true>
|
||||
*/
|
||||
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
|
||||
$opposite = Facing::opposite($constraint & ~RailConnectionInfo::FLAG_ASCEND);
|
||||
|
||||
$possible = [$opposite => true];
|
||||
|
||||
if(($constraint & RailConnectionInfo::FLAG_ASCEND) === 0){
|
||||
//We can slope the other way if this connection isn't already a slope
|
||||
$possible[$opposite | RailConnectionInfo::FLAG_ASCEND] = true;
|
||||
}
|
||||
|
||||
return $possible;
|
||||
}
|
||||
|
||||
private function tryReconnect() : void{
|
||||
$thisConnections = $this->getConnectedDirections();
|
||||
$changed = false;
|
||||
|
||||
$world = $this->position->getWorld();
|
||||
do{
|
||||
$possible = $this->getPossibleConnectionDirections($thisConnections);
|
||||
$continue = false;
|
||||
|
||||
foreach($possible as $thisSide => $_){
|
||||
$otherSide = Facing::opposite($thisSide & ~RailConnectionInfo::FLAG_ASCEND);
|
||||
|
||||
$other = $this->getSide($thisSide & ~RailConnectionInfo::FLAG_ASCEND);
|
||||
|
||||
if(($thisSide & RailConnectionInfo::FLAG_ASCEND) !== 0){
|
||||
$other = $other->getSide(Facing::UP);
|
||||
|
||||
}elseif(!($other instanceof BaseRail)){ //check if other rails can slope up to meet this one
|
||||
$other = $other->getSide(Facing::DOWN);
|
||||
$otherSide |= RailConnectionInfo::FLAG_ASCEND;
|
||||
}
|
||||
|
||||
if(!($other instanceof BaseRail) || count($otherConnections = $other->getConnectedDirections()) >= 2){
|
||||
//we can only connect to a rail that has less than 2 connections
|
||||
continue;
|
||||
}
|
||||
|
||||
$otherPossible = $other->getPossibleConnectionDirections($otherConnections);
|
||||
|
||||
if(isset($otherPossible[$otherSide])){
|
||||
$otherConnections[] = $otherSide;
|
||||
$other->setConnections($otherConnections);
|
||||
$world->setBlock($other->position, $other);
|
||||
|
||||
$changed = true;
|
||||
$thisConnections[] = $thisSide;
|
||||
$continue = count($thisConnections) < 2;
|
||||
|
||||
break; //force recomputing possible directions, since this connection could invalidate others
|
||||
}
|
||||
}
|
||||
}while($continue);
|
||||
|
||||
if($changed){
|
||||
$this->setConnections($thisConnections);
|
||||
$world->setBlock($this->position, $this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $connections
|
||||
*/
|
||||
private function setConnections(array $connections) : void{
|
||||
if(count($connections) === 1){
|
||||
$connections[] = Facing::opposite($connections[0] & ~RailConnectionInfo::FLAG_ASCEND);
|
||||
}elseif(count($connections) !== 2){
|
||||
throw new \InvalidArgumentException("Expected exactly 2 connections, got " . count($connections));
|
||||
}
|
||||
|
||||
$this->setShapeFromConnections($connections);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$world = $this->position->getWorld();
|
||||
if(!$this->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
|
||||
$world->useBreakOn($this->position);
|
||||
}else{
|
||||
foreach($this->getCurrentShapeConnections() as $connection){
|
||||
if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0 && !$this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND)->getSupportType(Facing::UP)->hasEdgeSupport()){
|
||||
$world->useBreakOn($this->position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,238 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Sign as TileSign;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\block\utils\SignText;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\block\utils\WoodType;
|
||||
use pocketmine\block\utils\WoodTypeTrait;
|
||||
use pocketmine\color\Color;
|
||||
use pocketmine\event\block\SignChangeEvent;
|
||||
use pocketmine\item\Dye;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemTypeIds;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\DyeUseSound;
|
||||
use pocketmine\world\sound\InkSacUseSound;
|
||||
use function array_map;
|
||||
use function assert;
|
||||
use function strlen;
|
||||
|
||||
abstract class BaseSign extends Transparent{
|
||||
use WoodTypeTrait;
|
||||
|
||||
protected SignText $text;
|
||||
protected ?int $editorEntityRuntimeId = null;
|
||||
|
||||
/** @var \Closure() : Item */
|
||||
private \Closure $asItemCallback;
|
||||
|
||||
/**
|
||||
* @param \Closure() : Item $asItemCallback
|
||||
*/
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo, WoodType $woodType, \Closure $asItemCallback){
|
||||
$this->woodType = $woodType;
|
||||
parent::__construct($idInfo, $name, $typeInfo);
|
||||
$this->text = new SignText();
|
||||
$this->asItemCallback = $asItemCallback;
|
||||
}
|
||||
|
||||
public function readStateFromWorld() : Block{
|
||||
parent::readStateFromWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
if($tile instanceof TileSign){
|
||||
$this->text = $tile->getText();
|
||||
$this->editorEntityRuntimeId = $tile->getEditorEntityRuntimeId();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
assert($tile instanceof TileSign);
|
||||
$tile->setText($this->text);
|
||||
$tile->setEditorEntityRuntimeId($this->editorEntityRuntimeId);
|
||||
}
|
||||
|
||||
public function isSolid() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getMaxStackSize() : int{
|
||||
return 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
abstract protected function getSupportingFace() : int;
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide($this->getSupportingFace())->getTypeId() === BlockTypeIds::AIR){
|
||||
$this->position->getWorld()->useBreakOn($this->position);
|
||||
}
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$this->editorEntityRuntimeId = $player->getId();
|
||||
}
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onPostPlace() : void{
|
||||
$player = $this->editorEntityRuntimeId !== null ?
|
||||
$this->position->getWorld()->getEntity($this->editorEntityRuntimeId) :
|
||||
null;
|
||||
if($player instanceof Player){
|
||||
$player->openSignEditor($this->position);
|
||||
}
|
||||
}
|
||||
|
||||
private function doSignChange(SignText $newText, Player $player, Item $item) : bool{
|
||||
$ev = new SignChangeEvent($this, $player, $newText);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->text = $ev->getNewText();
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
$item->pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function changeSignGlowingState(bool $glowing, Player $player, Item $item) : bool{
|
||||
if($this->text->isGlowing() !== $glowing && $this->doSignChange(new SignText($this->text->getLines(), $this->text->getBaseColor(), $glowing), $player, $item)){
|
||||
$this->position->getWorld()->addSound($this->position, new InkSacUseSound());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player === null){
|
||||
return false;
|
||||
}
|
||||
$dyeColor = $item instanceof Dye ? $item->getColor() : match($item->getTypeId()){
|
||||
ItemTypeIds::BONE_MEAL => DyeColor::WHITE(),
|
||||
ItemTypeIds::LAPIS_LAZULI => DyeColor::BLUE(),
|
||||
ItemTypeIds::COCOA_BEANS => DyeColor::BROWN(),
|
||||
default => null
|
||||
};
|
||||
if($dyeColor !== null){
|
||||
$color = $dyeColor->equals(DyeColor::BLACK()) ? new Color(0, 0, 0) : $dyeColor->getRgbValue();
|
||||
if($color->toARGB() === $this->text->getBaseColor()->toARGB()){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->doSignChange(new SignText($this->text->getLines(), $color, $this->text->isGlowing()), $player, $item)){
|
||||
$this->position->getWorld()->addSound($this->position, new DyeUseSound());
|
||||
return true;
|
||||
}
|
||||
}elseif($item->getTypeId() === ItemTypeIds::INK_SAC){
|
||||
return $this->changeSignGlowingState(false, $player, $item);
|
||||
}elseif($item->getTypeId() === ItemTypeIds::GLOW_INK_SAC){
|
||||
return $this->changeSignGlowingState(true, $player, $item);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object containing information about the sign text.
|
||||
*/
|
||||
public function getText() : SignText{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function setText(SignText $text) : self{
|
||||
$this->text = $text;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the runtime entity ID of the player editing this sign. Only this player will be able to edit the sign.
|
||||
* This is used to prevent multiple players from editing the same sign at the same time, and to prevent players
|
||||
* from editing signs they didn't place.
|
||||
*/
|
||||
public function getEditorEntityRuntimeId() : ?int{ return $this->editorEntityRuntimeId; }
|
||||
|
||||
/** @return $this */
|
||||
public function setEditorEntityRuntimeId(?int $editorEntityRuntimeId) : self{
|
||||
$this->editorEntityRuntimeId = $editorEntityRuntimeId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the player controller (network session) to update the sign text, firing events as appropriate.
|
||||
*
|
||||
* @return bool if the sign update was successful.
|
||||
* @throws \UnexpectedValueException if the text payload is too large
|
||||
*/
|
||||
public function updateText(Player $author, SignText $text) : bool{
|
||||
$size = 0;
|
||||
foreach($text->getLines() as $line){
|
||||
$size += strlen($line);
|
||||
}
|
||||
if($size > 1000){
|
||||
throw new \UnexpectedValueException($author->getName() . " tried to write $size bytes of text onto a sign (bigger than max 1000)");
|
||||
}
|
||||
$ev = new SignChangeEvent($this, $author, new SignText(array_map(function(string $line) : string{
|
||||
return TextFormat::clean($line, false);
|
||||
}, $text->getLines())));
|
||||
if($this->editorEntityRuntimeId === null || $this->editorEntityRuntimeId !== $author->getId()){
|
||||
$ev->cancel();
|
||||
}
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->setText($ev->getNewText());
|
||||
$this->setEditorEntityRuntimeId(null);
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return ($this->asItemCallback)();
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
final class Beacon extends Transparent{
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 15;
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
@ -1,216 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Bed as TileBed;
|
||||
use pocketmine\block\utils\ColoredTrait;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\World;
|
||||
|
||||
class Bed extends Transparent{
|
||||
use ColoredTrait;
|
||||
use HorizontalFacingTrait;
|
||||
|
||||
protected bool $occupied = false;
|
||||
protected bool $head = false;
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||
$this->color = DyeColor::RED();
|
||||
parent::__construct($idInfo, $name, $typeInfo);
|
||||
}
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->horizontalFacing($this->facing);
|
||||
$w->bool($this->occupied);
|
||||
$w->bool($this->head);
|
||||
}
|
||||
|
||||
public function readStateFromWorld() : Block{
|
||||
parent::readStateFromWorld();
|
||||
//read extra state information from the tile - this is an ugly hack
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
if($tile instanceof TileBed){
|
||||
$this->color = $tile->getColor();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
//extra block properties storage hack
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
if($tile instanceof TileBed){
|
||||
$tile->setColor($this->color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 16)];
|
||||
}
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
public function isHeadPart() : bool{
|
||||
return $this->head;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function setHead(bool $head) : self{
|
||||
$this->head = $head;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isOccupied() : bool{
|
||||
return $this->occupied;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function setOccupied(bool $occupied = true) : self{
|
||||
$this->occupied = $occupied;
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function getOtherHalfSide() : int{
|
||||
return $this->head ? Facing::opposite($this->facing) : $this->facing;
|
||||
}
|
||||
|
||||
public function getOtherHalf() : ?Bed{
|
||||
$other = $this->getSide($this->getOtherHalfSide());
|
||||
if($other instanceof Bed && $other->head !== $this->head && $other->facing === $this->facing){
|
||||
return $other;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
$other = $this->getOtherHalf();
|
||||
$playerPos = $player->getPosition();
|
||||
if($other === null){
|
||||
$player->sendMessage(TextFormat::GRAY . "This bed is incomplete");
|
||||
|
||||
return true;
|
||||
}elseif($playerPos->distanceSquared($this->position) > 4 && $playerPos->distanceSquared($other->position) > 4){
|
||||
$player->sendMessage(KnownTranslationFactory::tile_bed_tooFar()->prefix(TextFormat::GRAY));
|
||||
return true;
|
||||
}
|
||||
|
||||
$time = $this->position->getWorld()->getTimeOfDay();
|
||||
|
||||
$isNight = ($time >= World::TIME_NIGHT && $time < World::TIME_SUNRISE);
|
||||
|
||||
if(!$isNight){
|
||||
$player->sendMessage(KnownTranslationFactory::tile_bed_noSleep()->prefix(TextFormat::GRAY));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$b = ($this->isHeadPart() ? $this : $other);
|
||||
|
||||
if($b->isOccupied()){
|
||||
$player->sendMessage(KnownTranslationFactory::tile_bed_occupied()->prefix(TextFormat::GRAY));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$player->sleepOn($b->position);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->head && ($other = $this->getOtherHalf()) !== null && $other->occupied !== $this->occupied){
|
||||
$this->occupied = $other->occupied;
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function onEntityLand(Entity $entity) : ?float{
|
||||
if($entity instanceof Living && $entity->isSneaking()){
|
||||
return null;
|
||||
}
|
||||
$entity->fallDistance *= 0.5;
|
||||
return $entity->getMotion()->y * -3 / 4; // 2/3 in Java, according to the wiki
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($this->canBeSupportedBy($this->getSide(Facing::DOWN))){
|
||||
$this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH;
|
||||
|
||||
$next = $this->getSide($this->getOtherHalfSide());
|
||||
if($next->canBeReplaced() && $this->canBeSupportedBy($next->getSide(Facing::DOWN))){
|
||||
$nextState = clone $this;
|
||||
$nextState->head = true;
|
||||
$tx->addBlock($blockReplace->position, $this)->addBlock($next->position, $nextState);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->head){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getAffectedBlocks() : array{
|
||||
if(($other = $this->getOtherHalf()) !== null){
|
||||
return [$this, $other];
|
||||
}
|
||||
|
||||
return parent::getAffectedBlocks();
|
||||
}
|
||||
|
||||
private function canBeSupportedBy(Block $block) : bool{
|
||||
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
|
||||
}
|
||||
|
||||
public function getMaxStackSize() : int{ return 1; }
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
|
||||
class Bedrock extends Opaque{
|
||||
private bool $burnsForever = false;
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->bool($this->burnsForever);
|
||||
}
|
||||
|
||||
public function burnsForever() : bool{
|
||||
return $this->burnsForever;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function setBurnsForever(bool $burnsForever) : self{
|
||||
$this->burnsForever = $burnsForever;
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use function mt_rand;
|
||||
|
||||
class Beetroot extends Crops{
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if($this->age >= self::MAX_AGE){
|
||||
return [
|
||||
VanillaItems::BEETROOT(),
|
||||
VanillaItems::BEETROOT_SEEDS()->setCount(mt_rand(0, 3))
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
VanillaItems::BEETROOT_SEEDS()
|
||||
];
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaItems::BEETROOT_SEEDS();
|
||||
}
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Bell as TileBell;
|
||||
use pocketmine\block\utils\BellAttachmentType;
|
||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\entity\projectile\Projectile;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\RayTraceResult;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\BellRingSound;
|
||||
|
||||
final class Bell extends Transparent{
|
||||
use HorizontalFacingTrait;
|
||||
|
||||
private BellAttachmentType $attachmentType;
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||
$this->attachmentType = BellAttachmentType::FLOOR();
|
||||
parent::__construct($idInfo, $name, $typeInfo);
|
||||
}
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->bellAttachmentType($this->attachmentType);
|
||||
$w->horizontalFacing($this->facing);
|
||||
}
|
||||
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
if($this->attachmentType->equals(BellAttachmentType::FLOOR())){
|
||||
return [
|
||||
AxisAlignedBB::one()->squash(Facing::axis($this->facing), 1 / 4)->trim(Facing::UP, 3 / 16)
|
||||
];
|
||||
}
|
||||
if($this->attachmentType->equals(BellAttachmentType::CEILING())){
|
||||
return [
|
||||
AxisAlignedBB::one()->contract(1 / 4, 0, 1 / 4)->trim(Facing::DOWN, 1 / 4)
|
||||
];
|
||||
}
|
||||
|
||||
$box = AxisAlignedBB::one()
|
||||
->squash(Facing::axis(Facing::rotateY($this->facing, true)), 1 / 4)
|
||||
->trim(Facing::UP, 1 / 16)
|
||||
->trim(Facing::DOWN, 1 / 4);
|
||||
|
||||
return [
|
||||
$this->attachmentType->equals(BellAttachmentType::ONE_WALL()) ? $box->trim($this->facing, 3 / 16) : $box
|
||||
];
|
||||
}
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return SupportType::NONE();
|
||||
}
|
||||
|
||||
public function getAttachmentType() : BellAttachmentType{ return $this->attachmentType; }
|
||||
|
||||
/** @return $this */
|
||||
public function setAttachmentType(BellAttachmentType $attachmentType) : self{
|
||||
$this->attachmentType = $attachmentType;
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function canBeSupportedBy(Block $block, int $face) : bool{
|
||||
return !$block->getSupportType($face)->equals(SupportType::NONE());
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($face === Facing::UP){
|
||||
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()), Facing::UP)){
|
||||
return false;
|
||||
}
|
||||
if($player !== null){
|
||||
$this->setFacing(Facing::opposite($player->getHorizontalFacing()));
|
||||
}
|
||||
$this->setAttachmentType(BellAttachmentType::FLOOR());
|
||||
}elseif($face === Facing::DOWN){
|
||||
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->up()), Facing::DOWN)){
|
||||
return false;
|
||||
}
|
||||
$this->setAttachmentType(BellAttachmentType::CEILING());
|
||||
}else{
|
||||
$this->setFacing($face);
|
||||
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide(Facing::opposite($face))), $face)){
|
||||
$this->setAttachmentType(BellAttachmentType::ONE_WALL());
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide($face)), Facing::opposite($face))){
|
||||
$this->setAttachmentType(BellAttachmentType::TWO_WALLS());
|
||||
}
|
||||
}
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(
|
||||
($this->attachmentType->equals(BellAttachmentType::CEILING()) && !$this->canBeSupportedBy($this->getSide(Facing::UP), Facing::DOWN)) ||
|
||||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && !$this->canBeSupportedBy($this->getSide(Facing::DOWN), Facing::UP)) ||
|
||||
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) && !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)) ||
|
||||
($this->attachmentType->equals(BellAttachmentType::TWO_WALLS()) && (!$this->canBeSupportedBy($this->getSide($this->facing), Facing::opposite($this->facing)) || !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)))
|
||||
){
|
||||
$this->position->getWorld()->useBreakOn($this->position);
|
||||
}
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player !== null){
|
||||
$faceHit = Facing::opposite($player->getHorizontalFacing());
|
||||
if($this->isValidFaceToRing($faceHit)){
|
||||
$this->ring($faceHit);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
|
||||
$faceHit = Facing::opposite($projectile->getHorizontalFacing());
|
||||
if($this->isValidFaceToRing($faceHit)){
|
||||
$this->ring($faceHit);
|
||||
}
|
||||
}
|
||||
|
||||
public function ring(int $faceHit) : void{
|
||||
$world = $this->position->getWorld();
|
||||
$world->addSound($this->position, new BellRingSound());
|
||||
$tile = $world->getTile($this->position);
|
||||
if($tile instanceof TileBell){
|
||||
$world->broadcastPacketToViewers($this->position, $tile->createFakeUpdatePacket($faceHit));
|
||||
}
|
||||
}
|
||||
|
||||
private function isValidFaceToRing(int $faceHit) : bool{
|
||||
return (
|
||||
$this->attachmentType->equals(BellAttachmentType::CEILING()) ||
|
||||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)) ||
|
||||
(
|
||||
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) || $this->attachmentType->equals(BellAttachmentType::TWO_WALLS())) &&
|
||||
($faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -1,901 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* All Block classes are in here
|
||||
*/
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Spawnable;
|
||||
use pocketmine\block\tile\Tile;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\data\runtime\InvalidSerializedRuntimeDataException;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\data\runtime\RuntimeDataReader;
|
||||
use pocketmine\data\runtime\RuntimeDataSizeCalculator;
|
||||
use pocketmine\data\runtime\RuntimeDataWriter;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\projectile\Projectile;
|
||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemBlock;
|
||||
use pocketmine\math\Axis;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\RayTraceResult;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\format\Chunk;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\World;
|
||||
use function count;
|
||||
use function get_class;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
class Block{
|
||||
public const INTERNAL_STATE_DATA_BITS = 8;
|
||||
public const INTERNAL_STATE_DATA_MASK = ~(~0 << self::INTERNAL_STATE_DATA_BITS);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public const EMPTY_STATE_ID = (BlockTypeIds::AIR << self::INTERNAL_STATE_DATA_BITS) | (BlockTypeIds::AIR & self::INTERNAL_STATE_DATA_MASK);
|
||||
|
||||
protected BlockIdentifier $idInfo;
|
||||
protected string $fallbackName;
|
||||
protected BlockTypeInfo $typeInfo;
|
||||
protected Position $position;
|
||||
|
||||
/** @var AxisAlignedBB[]|null */
|
||||
protected ?array $collisionBoxes = null;
|
||||
|
||||
private int $requiredBlockItemStateDataBits;
|
||||
private int $requiredBlockOnlyStateDataBits;
|
||||
|
||||
private Block $defaultState;
|
||||
|
||||
/**
|
||||
* @param string $name English name of the block type (TODO: implement translations)
|
||||
*/
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||
$this->idInfo = $idInfo;
|
||||
$this->fallbackName = $name;
|
||||
$this->typeInfo = $typeInfo;
|
||||
$this->position = new Position(0, 0, 0, null);
|
||||
|
||||
$calculator = new RuntimeDataSizeCalculator();
|
||||
$this->describeBlockItemState($calculator);
|
||||
$this->requiredBlockItemStateDataBits = $calculator->getBitsUsed();
|
||||
|
||||
$calculator = new RuntimeDataSizeCalculator();
|
||||
$this->describeBlockOnlyState($calculator);
|
||||
$this->requiredBlockOnlyStateDataBits = $calculator->getBitsUsed();
|
||||
|
||||
$defaultState = clone $this;
|
||||
$this->defaultState = $defaultState;
|
||||
$defaultState->defaultState = $defaultState;
|
||||
}
|
||||
|
||||
public function __clone(){
|
||||
$this->position = clone $this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object containing information about how to identify and store this block type, such as type ID and
|
||||
* tile type (if any).
|
||||
*/
|
||||
public function getIdInfo() : BlockIdentifier{
|
||||
return $this->idInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the printable English name of the block.
|
||||
*/
|
||||
public function getName() : string{
|
||||
return $this->fallbackName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a type ID that identifies this type of block. This allows comparing basic block types, e.g. wool, stone,
|
||||
* glass, etc. Type ID will not change for a given block type.
|
||||
*
|
||||
* Information such as colour, powered, open/closed, etc. is **not** included in this ID.
|
||||
* If you want to get a state ID that includes this information, use {@link Block::getStateId()} instead.
|
||||
*
|
||||
* @see BlockTypeIds
|
||||
*/
|
||||
public function getTypeId() : int{
|
||||
return $this->idInfo->getBlockTypeId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Returns the full blockstate ID of this block. This is a compact way of representing a blockstate used to store
|
||||
* blocks in chunks at runtime.
|
||||
*
|
||||
* This usually encodes all properties of the block, such as facing, open/closed, powered/unpowered, colour, etc.
|
||||
* State ID may change depending on the properties of the block (e.g. a torch facing east will have a different
|
||||
* state ID to one facing west).
|
||||
*
|
||||
* Some blocks (such as signs and chests) may store additional properties in an associated "tile" if they
|
||||
* have too many possible values to be encoded into the state ID. These extra properties are **NOT** included in
|
||||
* this function's result.
|
||||
*
|
||||
* This ID can be used to later obtain a copy of the block with the same state properties by using
|
||||
* {@link RuntimeBlockStateRegistry::fromStateId()}.
|
||||
*/
|
||||
public function getStateId() : int{
|
||||
$typeId = $this->getTypeId();
|
||||
//TODO: this XOR mask improves hashtable distribution, but it's only effective if the number of unique block
|
||||
//type IDs is larger than the number of available state data bits. We should probably hash (e.g. using xxhash)
|
||||
//the type ID to create a better mask.
|
||||
//Alternatively, we could hash the whole state ID, but this is currently problematic, since we currently need
|
||||
//to be able to recover the state data from the state ID because of UnknownBlock.
|
||||
return ($typeId << self::INTERNAL_STATE_DATA_BITS) | ($this->encodeFullState() ^ ($typeId & self::INTERNAL_STATE_DATA_MASK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given block has the same type ID as this one.
|
||||
*/
|
||||
public function hasSameTypeId(Block $other) : bool{
|
||||
return $this->getTypeId() === $other->getTypeId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given block has the same type and properties as this block.
|
||||
*
|
||||
* Note: Tile data (e.g. sign text, chest contents) are not compared here.
|
||||
*/
|
||||
public function isSameState(Block $other) : bool{
|
||||
return $this->getStateId() === $other->getStateId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getTypeTags() : array{
|
||||
return $this->typeInfo->getTypeTags();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block type has the given type tag. Type tags are used as a dynamic way to tag blocks as
|
||||
* having certain properties, allowing type checks which are more dynamic than hardcoding a bunch of IDs or a bunch
|
||||
* of instanceof checks.
|
||||
*
|
||||
* For example, grass blocks, dirt, farmland, podzol and mycelium are all dirt-like blocks, and support the
|
||||
* placement of blocks like flowers, so they have a common tag which allows them to be identified as such.
|
||||
*/
|
||||
public function hasTypeTag(string $tag) : bool{
|
||||
return $this->typeInfo->hasTypeTag($tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block as an item.
|
||||
* Block-only state such as facing, powered/unpowered, open/closed, etc., is discarded.
|
||||
* Block-item state such as colour, wood type, etc. is preserved.
|
||||
* Complex state properties stored in the tile data (e.g. inventory) are discarded.
|
||||
*/
|
||||
public function asItem() : Item{
|
||||
$normalized = clone $this->defaultState;
|
||||
$normalized->decodeBlockItemState($this->encodeBlockItemState());
|
||||
return new ItemBlock($normalized);
|
||||
}
|
||||
|
||||
private function decodeBlockItemState(int $data) : void{
|
||||
$reader = new RuntimeDataReader($this->requiredBlockItemStateDataBits, $data);
|
||||
|
||||
$this->describeBlockItemState($reader);
|
||||
$readBits = $reader->getOffset();
|
||||
if($this->requiredBlockItemStateDataBits !== $readBits){
|
||||
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockItemStateDataBits bits of block-item state data were provided, but $readBits were read");
|
||||
}
|
||||
}
|
||||
|
||||
private function decodeBlockOnlyState(int $data) : void{
|
||||
$reader = new RuntimeDataReader($this->requiredBlockOnlyStateDataBits, $data);
|
||||
|
||||
$this->describeBlockOnlyState($reader);
|
||||
$readBits = $reader->getOffset();
|
||||
if($this->requiredBlockOnlyStateDataBits !== $readBits){
|
||||
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockOnlyStateDataBits bits of block-only state data were provided, but $readBits were read");
|
||||
}
|
||||
}
|
||||
|
||||
private function decodeFullState(int $data) : void{
|
||||
$reader = new RuntimeDataReader($this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits, $data);
|
||||
$this->decodeBlockItemState($reader->readInt($this->requiredBlockItemStateDataBits));
|
||||
$this->decodeBlockOnlyState($reader->readInt($this->requiredBlockOnlyStateDataBits));
|
||||
}
|
||||
|
||||
private function encodeBlockItemState() : int{
|
||||
$writer = new RuntimeDataWriter($this->requiredBlockItemStateDataBits);
|
||||
|
||||
$this->describeBlockItemState($writer);
|
||||
$writtenBits = $writer->getOffset();
|
||||
if($this->requiredBlockItemStateDataBits !== $writtenBits){
|
||||
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockItemStateDataBits bits of block-item state data were expected, but $writtenBits were written");
|
||||
}
|
||||
|
||||
return $writer->getValue();
|
||||
}
|
||||
|
||||
private function encodeBlockOnlyState() : int{
|
||||
$writer = new RuntimeDataWriter($this->requiredBlockOnlyStateDataBits);
|
||||
|
||||
$this->describeBlockOnlyState($writer);
|
||||
$writtenBits = $writer->getOffset();
|
||||
if($this->requiredBlockOnlyStateDataBits !== $writtenBits){
|
||||
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockOnlyStateDataBits bits of block-only state data were expected, but $writtenBits were written");
|
||||
}
|
||||
|
||||
return $writer->getValue();
|
||||
}
|
||||
|
||||
private function encodeFullState() : int{
|
||||
$writer = new RuntimeDataWriter($this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits);
|
||||
$writer->writeInt($this->requiredBlockItemStateDataBits, $this->encodeBlockItemState());
|
||||
$writer->writeInt($this->requiredBlockOnlyStateDataBits, $this->encodeBlockOnlyState());
|
||||
|
||||
return $writer->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes properties of this block which apply to both the block and item form of the block.
|
||||
* Examples of suitable properties include colour, skull type, and any other information which **IS** kept when the
|
||||
* block is mined or block-picked.
|
||||
*
|
||||
* The method implementation must NOT use conditional logic to determine which properties are written. It must
|
||||
* always write the same properties in the same order, regardless of the current state of the block.
|
||||
*/
|
||||
public function describeBlockItemState(RuntimeDataDescriber $w) : void{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes properties of this block which apply only to the block form of the block.
|
||||
* Examples of suitable properties include facing, open/closed, powered/unpowered, on/off, and any other information
|
||||
* which **IS NOT** kept when the block is mined or block-picked.
|
||||
*
|
||||
* The method implementation must NOT use conditional logic to determine which properties are written. It must
|
||||
* always write the same properties in the same order, regardless of the current state of the block.
|
||||
*/
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates copies of this Block in all possible state permutations.
|
||||
* Every possible combination of known properties (e.g. facing, open/closed, powered/unpowered, on/off) will be
|
||||
* generated.
|
||||
*
|
||||
* @phpstan-return \Generator<int, Block, void, void>
|
||||
*/
|
||||
public function generateStatePermutations() : \Generator{
|
||||
//TODO: this bruteforce approach to discovering all valid states is very inefficient for larger state data sizes
|
||||
//at some point we'll need to find a better way to do this
|
||||
$bits = $this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits;
|
||||
if($bits > Block::INTERNAL_STATE_DATA_BITS){
|
||||
throw new \LogicException("Block state data cannot use more than " . Block::INTERNAL_STATE_DATA_BITS . " bits");
|
||||
}
|
||||
for($stateData = 0; $stateData < (1 << $bits); ++$stateData){
|
||||
$v = clone $this;
|
||||
try{
|
||||
$v->decodeFullState($stateData);
|
||||
if($v->encodeFullState() !== $stateData){
|
||||
throw new \LogicException(static::class . "::decodeStateData() accepts invalid state data (returned " . $v->encodeFullState() . " for input $stateData)");
|
||||
}
|
||||
}catch(InvalidSerializedRuntimeDataException){ //invalid property combination, leave it
|
||||
continue;
|
||||
}
|
||||
|
||||
yield $v;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block is created, set, or has a neighbouring block update, to re-detect dynamic properties which
|
||||
* are not saved on the world.
|
||||
*
|
||||
* Clears any cached precomputed objects, such as bounding boxes. Remove any outdated precomputed things such as
|
||||
* AABBs and force recalculation.
|
||||
*
|
||||
* A replacement block may be returned. This is useful if the block type changed due to reading of world data (e.g.
|
||||
* data from a block entity).
|
||||
*/
|
||||
public function readStateFromWorld() : Block{
|
||||
$this->collisionBoxes = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes information about the block into the world. This writes the blockstate ID into the chunk, and creates
|
||||
* and/or removes tiles as necessary.
|
||||
*
|
||||
* Note: Do not call this directly. Pass the block to {@link World::setBlock()} instead.
|
||||
*/
|
||||
public function writeStateToWorld() : void{
|
||||
$world = $this->position->getWorld();
|
||||
$chunk = $world->getOrLoadChunkAtPosition($this->position);
|
||||
if($chunk === null){
|
||||
throw new AssumptionFailedError("World::setBlock() should have loaded the chunk before calling this method");
|
||||
}
|
||||
$chunk->setBlockStateId($this->position->x & Chunk::COORD_MASK, $this->position->y, $this->position->z & Chunk::COORD_MASK, $this->getStateId());
|
||||
|
||||
$tileType = $this->idInfo->getTileClass();
|
||||
$oldTile = $world->getTile($this->position);
|
||||
if($oldTile !== null){
|
||||
if($tileType === null || !($oldTile instanceof $tileType)){
|
||||
$oldTile->close();
|
||||
$oldTile = null;
|
||||
}elseif($oldTile instanceof Spawnable){
|
||||
$oldTile->clearSpawnCompoundCache(); //destroy old network cache
|
||||
}
|
||||
}
|
||||
if($oldTile === null && $tileType !== null){
|
||||
/**
|
||||
* @var Tile $tile
|
||||
* @see Tile::__construct()
|
||||
*/
|
||||
$tile = new $tileType($world, $this->position->asVector3());
|
||||
$world->addTile($tile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AKA: Block->isPlaceable
|
||||
*/
|
||||
public function canBePlaced() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block can be replaced by another block placed in the same position.
|
||||
*/
|
||||
public function canBeReplaced() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block can replace the given block in the given placement conditions.
|
||||
* This is used to allow slabs of the same type to combine into double slabs.
|
||||
*/
|
||||
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
|
||||
return $blockReplace->canBeReplaced();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a block transaction to set all blocks affected by placing this block. Usually this is just the block
|
||||
* itself, but may be multiple blocks in some cases (such as doors).
|
||||
*
|
||||
* @param BlockTransaction $tx Blocks to be set should be added to this transaction (do not modify thr world directly)
|
||||
* @param Item $item Item used to place the block
|
||||
* @param Block $blockReplace Block expected to be replaced
|
||||
* @param Block $blockClicked Block that was clicked using the item
|
||||
* @param int $face Face of the clicked block which was clicked
|
||||
* @param Vector3 $clickVector Exact position inside the clicked block where the click occurred, relative to the block's position
|
||||
* @param Player|null $player Player who placed the block, or null if it was not a player
|
||||
*
|
||||
* @return bool whether the placement should go ahead
|
||||
*/
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$tx->addBlock($blockReplace->position, $this);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called immediately after the block has been placed in the world. Since placement uses a block transaction, some
|
||||
* things may not be possible until after the transaction has been executed.
|
||||
*/
|
||||
public function onPostPlace() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object containing information about the destruction requirements of this block.
|
||||
*/
|
||||
public function getBreakInfo() : BlockBreakInfo{
|
||||
return $this->typeInfo->getBreakInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the actions needed so the block is broken with the Item
|
||||
*
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if full)
|
||||
*/
|
||||
public function onBreak(Item $item, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$world = $this->position->getWorld();
|
||||
if(($t = $world->getTile($this->position)) !== null){
|
||||
$t->onBlockDestroyed();
|
||||
}
|
||||
$world->setBlock($this->position, VanillaBlocks::AIR());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block or a block immediately adjacent to it changes state.
|
||||
*/
|
||||
public function onNearbyBlockChange() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether random block updates will be done on this block.
|
||||
*/
|
||||
public function ticksRandomly() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block is randomly updated due to chunk ticking.
|
||||
* WARNING: This will not be called if {@link Block::ticksRandomly()} does not return true!
|
||||
*/
|
||||
public function onRandomTick() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block is updated by the delayed blockupdate scheduler in the world.
|
||||
*/
|
||||
public function onScheduledUpdate() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Do actions when interacted by Item. Returns if it has done anything
|
||||
*
|
||||
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
|
||||
*/
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block is attacked (left-clicked) by a player attempting to start breaking it in survival.
|
||||
*
|
||||
* @return bool if an action took place, prevents starting to break the block if true.
|
||||
*/
|
||||
public function onAttack(Item $item, int $face, ?Player $player = null) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a multiplier applied to the velocity of entities moving on top of this block. A higher value will make
|
||||
* the block more slippery (like ice).
|
||||
*
|
||||
* @return float 0.0-1.0
|
||||
*/
|
||||
public function getFrictionFactor() : float{
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of light emitted by this block.
|
||||
*
|
||||
* @return int 0-15
|
||||
*/
|
||||
public function getLightLevel() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of light this block will filter out when light passes through this block.
|
||||
* This value is used in light spread calculation.
|
||||
*
|
||||
* @return int 0-15
|
||||
*/
|
||||
public function getLightFilter() : int{
|
||||
return $this->isTransparent() ? 0 : 15;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block blocks direct sky light from passing through it. This is independent from the light
|
||||
* filter value, which is used during propagation.
|
||||
*
|
||||
* In most cases, this is the same as isTransparent(); however, some special cases exist such as leaves and cobwebs,
|
||||
* which don't have any additional effect on light propagation, but don't allow direct sky light to pass through.
|
||||
*/
|
||||
public function blocksDirectSkyLight() : bool{
|
||||
return $this->getLightFilter() > 0;
|
||||
}
|
||||
|
||||
public function isTransparent() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isSolid() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* AKA: Block->isFlowable
|
||||
*/
|
||||
public function canBeFlowedInto() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether entities can climb up this block.
|
||||
*/
|
||||
public function canClimb() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
final public function getPosition() : Position{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final public function position(World $world, int $x, int $y, int $z) : void{
|
||||
$this->position = new Position($x, $y, $z, $world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of Item objects to be dropped
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->getBreakInfo()->isToolCompatible($item)){
|
||||
if($this->isAffectedBySilkTouch() && $item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
|
||||
return $this->getSilkTouchDrops($item);
|
||||
}
|
||||
|
||||
return $this->getDropsForCompatibleTool($item);
|
||||
}
|
||||
|
||||
return $this->getDropsForIncompatibleTool($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of Items to be dropped when the block is broken using the correct tool type.
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [$this->asItem()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the items dropped by this block when broken with an incorrect tool type (or tool with a too-low tier).
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getDropsForIncompatibleTool(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of Items to be dropped when the block is broken using a compatible Silk Touch-enchanted tool.
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getSilkTouchDrops(Item $item) : array{
|
||||
return [$this->asItem()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how much XP will be dropped by breaking this block with the given item.
|
||||
*/
|
||||
public function getXpDropForTool(Item $item) : int{
|
||||
if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH()) || !$this->getBreakInfo()->isToolCompatible($item)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $this->getXpDropAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how much XP this block will drop when broken with an appropriate tool.
|
||||
*/
|
||||
protected function getXpDropAmount() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether Silk Touch enchanted tools will cause this block to drop as itself.
|
||||
*/
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item that players will equip when middle-clicking on this block.
|
||||
* If addUserData is true, additional data may be added, such as banner patterns, chest contents, etc.
|
||||
*/
|
||||
public function getPickedItem(bool $addUserData = false) : Item{
|
||||
$item = $this->asItem();
|
||||
if($addUserData){
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
if($tile instanceof Tile){
|
||||
$nbt = $tile->getCleanedNBT();
|
||||
if($nbt instanceof CompoundTag){
|
||||
$item->setCustomBlockData($nbt);
|
||||
$item->setLore(["+(DATA)"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time in ticks which the block will fuel a furnace for.
|
||||
*/
|
||||
public function getFuelTime() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of this block that can fit into a single item stack.
|
||||
*/
|
||||
public function getMaxStackSize() : int{
|
||||
return 64;
|
||||
}
|
||||
|
||||
public function isFireProofAsItem() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the chance that the block will catch fire from nearby fire sources. Higher values lead to faster catching
|
||||
* fire.
|
||||
*/
|
||||
public function getFlameEncouragement() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base flammability of this block. Higher values lead to the block burning away more quickly.
|
||||
*/
|
||||
public function getFlammability() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether fire lit on this block will burn indefinitely.
|
||||
*/
|
||||
public function burnsForever() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block can catch fire.
|
||||
*/
|
||||
public function isFlammable() : bool{
|
||||
return $this->getFlammability() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this block is burned away by being on fire.
|
||||
*/
|
||||
public function onIncinerate() : void{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Block on the side $side, works like Vector3::getSide()
|
||||
*
|
||||
* @return Block
|
||||
*/
|
||||
public function getSide(int $side, int $step = 1){
|
||||
if($this->position->isValid()){
|
||||
return $this->position->getWorld()->getBlock($this->position->getSide($side, $step));
|
||||
}
|
||||
|
||||
throw new \LogicException("Block does not have a valid world");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 4 blocks on the horizontal axes around the block (north, south, east, west)
|
||||
*
|
||||
* @return Block[]|\Generator
|
||||
* @phpstan-return \Generator<int, Block, void, void>
|
||||
*/
|
||||
public function getHorizontalSides() : \Generator{
|
||||
$world = $this->position->getWorld();
|
||||
foreach($this->position->sidesAroundAxis(Axis::Y) as $vector3){
|
||||
yield $world->getBlock($vector3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the six blocks around this block.
|
||||
*
|
||||
* @return Block[]|\Generator
|
||||
* @phpstan-return \Generator<int, Block, void, void>
|
||||
*/
|
||||
public function getAllSides() : \Generator{
|
||||
$world = $this->position->getWorld();
|
||||
foreach($this->position->sides() as $vector3){
|
||||
yield $world->getBlock($vector3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of blocks that this block is part of. In most cases, only contains the block itself, but in cases
|
||||
* such as double plants, beds and doors, will contain both halves.
|
||||
*
|
||||
* @return Block[]
|
||||
*/
|
||||
public function getAffectedBlocks() : array{
|
||||
return [$this];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(){
|
||||
return "Block[" . $this->getName() . "] (" . $this->getTypeId() . ":" . $this->encodeFullState() . ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether any of the block's collision boxes intersect with the given AxisAlignedBB.
|
||||
*/
|
||||
public function collidesWithBB(AxisAlignedBB $bb) : bool{
|
||||
foreach($this->getCollisionBoxes() as $bb2){
|
||||
if($bb->intersectsWith($bb2)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the block has actions to be executed when an entity enters its cell (full cube space).
|
||||
*
|
||||
* @see Block::onEntityInside()
|
||||
*/
|
||||
public function hasEntityCollision() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an entity's bounding box clips inside this block's cell. Note that the entity may not be intersecting
|
||||
* with the collision box or bounding box.
|
||||
*
|
||||
* WARNING: This will not be called if {@link Block::hasEntityCollision()} returns false.
|
||||
*
|
||||
* @return bool Whether the block is still the same after the intersection. If it changed (e.g. due to an explosive
|
||||
* being ignited), this should return false.
|
||||
*/
|
||||
public function onEntityInside(Entity $entity) : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a direction vector describing which way an entity intersecting this block should be pushed.
|
||||
* This is used by liquids to push entities in liquid currents.
|
||||
*
|
||||
* The returned vector is summed with vectors from every other block the entity is intersecting, and normalized to
|
||||
* produce a final direction vector.
|
||||
*
|
||||
* WARNING: This will not be called if {@link Block::hasEntityCollision()} does not return true!
|
||||
*/
|
||||
public function addVelocityToEntity(Entity $entity) : ?Vector3{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an entity lands on this block (usually due to falling).
|
||||
* @return float|null The new vertical velocity of the entity, or null if unchanged.
|
||||
*/
|
||||
public function onEntityLand(Entity $entity) : ?float{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a projectile collides with one of this block's collision boxes.
|
||||
*/
|
||||
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
|
||||
//NOOP
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of collision bounding boxes for this block.
|
||||
* These are used for:
|
||||
* - entity movement collision checks (to ensure entities can't clip through blocks)
|
||||
* - projectile flight paths
|
||||
* - block placement (to ensure the player can't place blocks inside itself or another entity)
|
||||
* - anti-cheat checks in plugins
|
||||
*
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
final public function getCollisionBoxes() : array{
|
||||
if($this->collisionBoxes === null){
|
||||
$this->collisionBoxes = $this->recalculateCollisionBoxes();
|
||||
$extraOffset = $this->getModelPositionOffset();
|
||||
$offset = $extraOffset !== null ? $this->position->addVector($extraOffset) : $this->position;
|
||||
foreach($this->collisionBoxes as $bb){
|
||||
$bb->offset($offset->x, $offset->y, $offset->z);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->collisionBoxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an additional fractional vector to shift the block model's position by based on the current position.
|
||||
* Used to randomize position of things like bamboo canes and tall grass.
|
||||
*/
|
||||
public function getModelPositionOffset() : ?Vector3{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
return [AxisAlignedBB::one()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of support that the block can provide on the given face. This is used to determine whether
|
||||
* blocks placed on the given face can be supported by this block.
|
||||
*/
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return SupportType::FULL();
|
||||
}
|
||||
|
||||
public function isFullCube() : bool{
|
||||
$bb = $this->getCollisionBoxes();
|
||||
|
||||
return count($bb) === 1 && $bb[0]->getAverageEdgeLength() >= 1 && $bb[0]->isCube();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a ray trace along the line between the two positions using the block's collision boxes.
|
||||
* Returns the intersection point closest to pos1, or null if no intersection occurred.
|
||||
*/
|
||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
|
||||
$bbs = $this->getCollisionBoxes();
|
||||
if(count($bbs) === 0){
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var RayTraceResult|null $currentHit */
|
||||
$currentHit = null;
|
||||
/** @var int|float $currentDistance */
|
||||
$currentDistance = PHP_INT_MAX;
|
||||
|
||||
foreach($bbs as $bb){
|
||||
$nextHit = $bb->calculateIntercept($pos1, $pos2);
|
||||
if($nextHit === null){
|
||||
continue;
|
||||
}
|
||||
|
||||
$nextDistance = $nextHit->hitVector->distanceSquared($pos1);
|
||||
if($nextDistance < $currentDistance){
|
||||
$currentHit = $nextHit;
|
||||
$currentDistance = $nextDistance;
|
||||
}
|
||||
}
|
||||
|
||||
return $currentHit;
|
||||
}
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ToolTier;
|
||||
use function get_class;
|
||||
|
||||
class BlockBreakInfo{
|
||||
/**
|
||||
* If the tool is the correct type and high enough harvest level (tool tier), base break time is hardness multiplied
|
||||
* by this value.
|
||||
*/
|
||||
public const COMPATIBLE_TOOL_MULTIPLIER = 1.5;
|
||||
/**
|
||||
* If the tool is an incorrect type or too low harvest level (tool tier), base break time is hardness multiplied by
|
||||
* this value.
|
||||
*/
|
||||
public const INCOMPATIBLE_TOOL_MULTIPLIER = 5.0;
|
||||
|
||||
private float $blastResistance;
|
||||
|
||||
/**
|
||||
* @param float|null $blastResistance default 5x hardness
|
||||
*/
|
||||
public function __construct(
|
||||
private float $hardness,
|
||||
private int $toolType = BlockToolType::NONE,
|
||||
private int $toolHarvestLevel = 0,
|
||||
?float $blastResistance = null
|
||||
){
|
||||
$this->blastResistance = $blastResistance ?? $hardness * 5;
|
||||
}
|
||||
|
||||
public static function tier(float $hardness, int $toolType, ToolTier $toolTier, ?float $blastResistance = null) : self{
|
||||
return new self($hardness, $toolType, $toolTier->getHarvestLevel(), $blastResistance);
|
||||
}
|
||||
|
||||
public static function pickaxe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : self{
|
||||
return new self($hardness, BlockToolType::PICKAXE, $toolTier?->getHarvestLevel() ?? 0, $blastResistance);
|
||||
}
|
||||
|
||||
public static function shovel(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : self{
|
||||
return new self($hardness, BlockToolType::SHOVEL, $toolTier?->getHarvestLevel() ?? 0, $blastResistance);
|
||||
}
|
||||
|
||||
public static function axe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : self{
|
||||
return new self($hardness, BlockToolType::AXE, $toolTier?->getHarvestLevel() ?? 0, $blastResistance);
|
||||
}
|
||||
|
||||
public static function instant(int $toolType = BlockToolType::NONE, int $toolHarvestLevel = 0) : self{
|
||||
return new self(0.0, $toolType, $toolHarvestLevel, 0.0);
|
||||
}
|
||||
|
||||
public static function indestructible(float $blastResistance = 18000000.0) : self{
|
||||
return new self(-1.0, BlockToolType::NONE, 0, $blastResistance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a base value used to compute block break times.
|
||||
*/
|
||||
public function getHardness() : float{
|
||||
return $this->hardness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the block can be broken at all.
|
||||
*/
|
||||
public function isBreakable() : bool{
|
||||
return $this->hardness >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block can be instantly broken.
|
||||
*/
|
||||
public function breaksInstantly() : bool{
|
||||
return $this->hardness == 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block's resistance to explosions. Usually 5x hardness.
|
||||
*/
|
||||
public function getBlastResistance() : float{
|
||||
return $this->blastResistance;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return $this->toolType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the level of tool required to harvest the block (for normal blocks). When the tool type matches the
|
||||
* block's required tool type, the tool must have a harvest level greater than or equal to this value to be able to
|
||||
* successfully harvest the block.
|
||||
*
|
||||
* If the block requires a specific minimum tier of tiered tool, the minimum tier required should be returned.
|
||||
* Otherwise, 1 should be returned if a tool is required, 0 if not.
|
||||
*
|
||||
* @see Item::getBlockToolHarvestLevel()
|
||||
*/
|
||||
public function getToolHarvestLevel() : int{
|
||||
return $this->toolHarvestLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified item is the proper tool to use for breaking this block. This checks tool type and
|
||||
* harvest level requirement.
|
||||
*
|
||||
* In most cases this is also used to determine whether block drops should be created or not, except in some
|
||||
* special cases such as vines.
|
||||
*/
|
||||
public function isToolCompatible(Item $tool) : bool{
|
||||
if($this->hardness < 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->toolType === BlockToolType::NONE || $this->toolHarvestLevel === 0 || (
|
||||
($this->toolType & $tool->getBlockToolType()) !== 0 && $tool->getBlockToolHarvestLevel() >= $this->toolHarvestLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the seconds that this block takes to be broken using an specific Item
|
||||
*
|
||||
* @throws \InvalidArgumentException if the item efficiency is not a positive number
|
||||
*/
|
||||
public function getBreakTime(Item $item) : float{
|
||||
$base = $this->hardness;
|
||||
if($this->isToolCompatible($item)){
|
||||
$base *= self::COMPATIBLE_TOOL_MULTIPLIER;
|
||||
}else{
|
||||
$base *= self::INCOMPATIBLE_TOOL_MULTIPLIER;
|
||||
}
|
||||
|
||||
$efficiency = $item->getMiningEfficiency(($this->toolType & $item->getBlockToolType()) !== 0);
|
||||
if($efficiency <= 0){
|
||||
throw new \InvalidArgumentException(get_class($item) . " has invalid mining efficiency: expected >= 0, got $efficiency");
|
||||
}
|
||||
|
||||
$base /= $efficiency;
|
||||
|
||||
return $base;
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Tile;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
class BlockIdentifier{
|
||||
/**
|
||||
* @phpstan-param class-string<Tile>|null $tileClass
|
||||
*/
|
||||
public function __construct(
|
||||
private int $blockTypeId,
|
||||
private ?string $tileClass = null
|
||||
){
|
||||
if($blockTypeId < 0){
|
||||
throw new \InvalidArgumentException("Block type ID may not be negative");
|
||||
}
|
||||
if($tileClass !== null){
|
||||
Utils::testValidInstance($tileClass, Tile::class);
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlockTypeId() : int{ return $this->blockTypeId; }
|
||||
|
||||
/**
|
||||
* @phpstan-return class-string<Tile>|null
|
||||
*/
|
||||
public function getTileClass() : ?string{
|
||||
return $this->tileClass;
|
||||
}
|
||||
}
|
@ -1,731 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
/**
|
||||
* Every block in {@link VanillaBlocks} has a corresponding constant in this class. These constants can be used to
|
||||
* identify and compare block types efficiently using {@link Block::getTypeId()}.
|
||||
*
|
||||
* Type ID is also used internally as part of block state ID, which is used to store blocks and their simple properties
|
||||
* in a memory-efficient way in chunks at runtime.
|
||||
*
|
||||
* WARNING: These are NOT a replacement for Minecraft legacy IDs. Do **NOT** hardcode their values, or store them in
|
||||
* configs or databases. They will change without warning.
|
||||
*/
|
||||
final class BlockTypeIds{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public const AIR = 10000;
|
||||
|
||||
public const ACACIA_BUTTON = 10001;
|
||||
public const ACACIA_DOOR = 10002;
|
||||
public const ACACIA_FENCE = 10003;
|
||||
public const ACACIA_FENCE_GATE = 10004;
|
||||
public const ACACIA_LEAVES = 10005;
|
||||
public const ACACIA_LOG = 10006;
|
||||
public const ACACIA_PLANKS = 10007;
|
||||
public const ACACIA_PRESSURE_PLATE = 10008;
|
||||
public const ACACIA_SAPLING = 10009;
|
||||
public const ACACIA_SIGN = 10010;
|
||||
public const ACACIA_SLAB = 10011;
|
||||
public const ACACIA_STAIRS = 10012;
|
||||
public const ACACIA_TRAPDOOR = 10013;
|
||||
public const ACACIA_WALL_SIGN = 10014;
|
||||
public const ACACIA_WOOD = 10015;
|
||||
public const ACTIVATOR_RAIL = 10016;
|
||||
public const ALL_SIDED_MUSHROOM_STEM = 10017;
|
||||
public const ALLIUM = 10018;
|
||||
public const ANDESITE = 10019;
|
||||
public const ANDESITE_SLAB = 10020;
|
||||
public const ANDESITE_STAIRS = 10021;
|
||||
public const ANDESITE_WALL = 10022;
|
||||
public const ANVIL = 10023;
|
||||
public const AZURE_BLUET = 10024;
|
||||
public const BAMBOO = 10025;
|
||||
public const BAMBOO_SAPLING = 10026;
|
||||
public const BANNER = 10027;
|
||||
public const BARREL = 10028;
|
||||
public const BARRIER = 10029;
|
||||
public const BEACON = 10030;
|
||||
public const BED = 10031;
|
||||
public const BEDROCK = 10032;
|
||||
public const BEETROOTS = 10033;
|
||||
public const BELL = 10034;
|
||||
public const BIRCH_BUTTON = 10035;
|
||||
public const BIRCH_DOOR = 10036;
|
||||
public const BIRCH_FENCE = 10037;
|
||||
public const BIRCH_FENCE_GATE = 10038;
|
||||
public const BIRCH_LEAVES = 10039;
|
||||
public const BIRCH_LOG = 10040;
|
||||
public const BIRCH_PLANKS = 10041;
|
||||
public const BIRCH_PRESSURE_PLATE = 10042;
|
||||
public const BIRCH_SAPLING = 10043;
|
||||
public const BIRCH_SIGN = 10044;
|
||||
public const BIRCH_SLAB = 10045;
|
||||
public const BIRCH_STAIRS = 10046;
|
||||
public const BIRCH_TRAPDOOR = 10047;
|
||||
public const BIRCH_WALL_SIGN = 10048;
|
||||
public const BIRCH_WOOD = 10049;
|
||||
|
||||
public const BLAST_FURNACE = 10051;
|
||||
|
||||
public const BLUE_ICE = 10053;
|
||||
public const BLUE_ORCHID = 10054;
|
||||
public const BLUE_TORCH = 10055;
|
||||
public const BONE_BLOCK = 10056;
|
||||
public const BOOKSHELF = 10057;
|
||||
public const BREWING_STAND = 10058;
|
||||
public const BRICK_SLAB = 10059;
|
||||
public const BRICK_STAIRS = 10060;
|
||||
public const BRICK_WALL = 10061;
|
||||
public const BRICKS = 10062;
|
||||
|
||||
public const BROWN_MUSHROOM = 10064;
|
||||
public const BROWN_MUSHROOM_BLOCK = 10065;
|
||||
public const CACTUS = 10066;
|
||||
public const CAKE = 10067;
|
||||
public const CARPET = 10068;
|
||||
public const CARROTS = 10069;
|
||||
public const CARVED_PUMPKIN = 10070;
|
||||
public const CHEMICAL_HEAT = 10071;
|
||||
public const CHEST = 10072;
|
||||
public const CHISELED_QUARTZ = 10073;
|
||||
public const CHISELED_RED_SANDSTONE = 10074;
|
||||
public const CHISELED_SANDSTONE = 10075;
|
||||
public const CHISELED_STONE_BRICKS = 10076;
|
||||
public const CLAY = 10077;
|
||||
public const COAL = 10078;
|
||||
public const COAL_ORE = 10079;
|
||||
public const COBBLESTONE = 10080;
|
||||
public const COBBLESTONE_SLAB = 10081;
|
||||
public const COBBLESTONE_STAIRS = 10082;
|
||||
public const COBBLESTONE_WALL = 10083;
|
||||
public const COBWEB = 10084;
|
||||
public const COCOA_POD = 10085;
|
||||
public const COMPOUND_CREATOR = 10086;
|
||||
public const CONCRETE = 10087;
|
||||
public const CONCRETE_POWDER = 10088;
|
||||
public const CORAL = 10089;
|
||||
public const CORAL_BLOCK = 10090;
|
||||
public const CORAL_FAN = 10091;
|
||||
public const CORNFLOWER = 10092;
|
||||
public const CRACKED_STONE_BRICKS = 10093;
|
||||
public const CRAFTING_TABLE = 10094;
|
||||
public const CUT_RED_SANDSTONE = 10095;
|
||||
public const CUT_RED_SANDSTONE_SLAB = 10096;
|
||||
public const CUT_SANDSTONE = 10097;
|
||||
public const CUT_SANDSTONE_SLAB = 10098;
|
||||
|
||||
public const DANDELION = 10100;
|
||||
public const DARK_OAK_BUTTON = 10101;
|
||||
public const DARK_OAK_DOOR = 10102;
|
||||
public const DARK_OAK_FENCE = 10103;
|
||||
public const DARK_OAK_FENCE_GATE = 10104;
|
||||
public const DARK_OAK_LEAVES = 10105;
|
||||
public const DARK_OAK_LOG = 10106;
|
||||
public const DARK_OAK_PLANKS = 10107;
|
||||
public const DARK_OAK_PRESSURE_PLATE = 10108;
|
||||
public const DARK_OAK_SAPLING = 10109;
|
||||
public const DARK_OAK_SIGN = 10110;
|
||||
public const DARK_OAK_SLAB = 10111;
|
||||
public const DARK_OAK_STAIRS = 10112;
|
||||
public const DARK_OAK_TRAPDOOR = 10113;
|
||||
public const DARK_OAK_WALL_SIGN = 10114;
|
||||
public const DARK_OAK_WOOD = 10115;
|
||||
public const DARK_PRISMARINE = 10116;
|
||||
public const DARK_PRISMARINE_SLAB = 10117;
|
||||
public const DARK_PRISMARINE_STAIRS = 10118;
|
||||
public const DAYLIGHT_SENSOR = 10119;
|
||||
public const DEAD_BUSH = 10120;
|
||||
public const DETECTOR_RAIL = 10121;
|
||||
public const DIAMOND = 10122;
|
||||
public const DIAMOND_ORE = 10123;
|
||||
public const DIORITE = 10124;
|
||||
public const DIORITE_SLAB = 10125;
|
||||
public const DIORITE_STAIRS = 10126;
|
||||
public const DIORITE_WALL = 10127;
|
||||
public const DIRT = 10128;
|
||||
public const DOUBLE_TALLGRASS = 10129;
|
||||
public const DRAGON_EGG = 10130;
|
||||
public const DRIED_KELP = 10131;
|
||||
public const DYED_SHULKER_BOX = 10132;
|
||||
public const ELEMENT_ACTINIUM = 10133;
|
||||
public const ELEMENT_ALUMINUM = 10134;
|
||||
public const ELEMENT_AMERICIUM = 10135;
|
||||
public const ELEMENT_ANTIMONY = 10136;
|
||||
public const ELEMENT_ARGON = 10137;
|
||||
public const ELEMENT_ARSENIC = 10138;
|
||||
public const ELEMENT_ASTATINE = 10139;
|
||||
public const ELEMENT_BARIUM = 10140;
|
||||
public const ELEMENT_BERKELIUM = 10141;
|
||||
public const ELEMENT_BERYLLIUM = 10142;
|
||||
public const ELEMENT_BISMUTH = 10143;
|
||||
public const ELEMENT_BOHRIUM = 10144;
|
||||
public const ELEMENT_BORON = 10145;
|
||||
public const ELEMENT_BROMINE = 10146;
|
||||
public const ELEMENT_CADMIUM = 10147;
|
||||
public const ELEMENT_CALCIUM = 10148;
|
||||
public const ELEMENT_CALIFORNIUM = 10149;
|
||||
public const ELEMENT_CARBON = 10150;
|
||||
public const ELEMENT_CERIUM = 10151;
|
||||
public const ELEMENT_CESIUM = 10152;
|
||||
public const ELEMENT_CHLORINE = 10153;
|
||||
public const ELEMENT_CHROMIUM = 10154;
|
||||
public const ELEMENT_COBALT = 10155;
|
||||
public const ELEMENT_CONSTRUCTOR = 10156;
|
||||
public const ELEMENT_COPERNICIUM = 10157;
|
||||
public const ELEMENT_COPPER = 10158;
|
||||
public const ELEMENT_CURIUM = 10159;
|
||||
public const ELEMENT_DARMSTADTIUM = 10160;
|
||||
public const ELEMENT_DUBNIUM = 10161;
|
||||
public const ELEMENT_DYSPROSIUM = 10162;
|
||||
public const ELEMENT_EINSTEINIUM = 10163;
|
||||
public const ELEMENT_ERBIUM = 10164;
|
||||
public const ELEMENT_EUROPIUM = 10165;
|
||||
public const ELEMENT_FERMIUM = 10166;
|
||||
public const ELEMENT_FLEROVIUM = 10167;
|
||||
public const ELEMENT_FLUORINE = 10168;
|
||||
public const ELEMENT_FRANCIUM = 10169;
|
||||
public const ELEMENT_GADOLINIUM = 10170;
|
||||
public const ELEMENT_GALLIUM = 10171;
|
||||
public const ELEMENT_GERMANIUM = 10172;
|
||||
public const ELEMENT_GOLD = 10173;
|
||||
public const ELEMENT_HAFNIUM = 10174;
|
||||
public const ELEMENT_HASSIUM = 10175;
|
||||
public const ELEMENT_HELIUM = 10176;
|
||||
public const ELEMENT_HOLMIUM = 10177;
|
||||
public const ELEMENT_HYDROGEN = 10178;
|
||||
public const ELEMENT_INDIUM = 10179;
|
||||
public const ELEMENT_IODINE = 10180;
|
||||
public const ELEMENT_IRIDIUM = 10181;
|
||||
public const ELEMENT_IRON = 10182;
|
||||
public const ELEMENT_KRYPTON = 10183;
|
||||
public const ELEMENT_LANTHANUM = 10184;
|
||||
public const ELEMENT_LAWRENCIUM = 10185;
|
||||
public const ELEMENT_LEAD = 10186;
|
||||
public const ELEMENT_LITHIUM = 10187;
|
||||
public const ELEMENT_LIVERMORIUM = 10188;
|
||||
public const ELEMENT_LUTETIUM = 10189;
|
||||
public const ELEMENT_MAGNESIUM = 10190;
|
||||
public const ELEMENT_MANGANESE = 10191;
|
||||
public const ELEMENT_MEITNERIUM = 10192;
|
||||
public const ELEMENT_MENDELEVIUM = 10193;
|
||||
public const ELEMENT_MERCURY = 10194;
|
||||
public const ELEMENT_MOLYBDENUM = 10195;
|
||||
public const ELEMENT_MOSCOVIUM = 10196;
|
||||
public const ELEMENT_NEODYMIUM = 10197;
|
||||
public const ELEMENT_NEON = 10198;
|
||||
public const ELEMENT_NEPTUNIUM = 10199;
|
||||
public const ELEMENT_NICKEL = 10200;
|
||||
public const ELEMENT_NIHONIUM = 10201;
|
||||
public const ELEMENT_NIOBIUM = 10202;
|
||||
public const ELEMENT_NITROGEN = 10203;
|
||||
public const ELEMENT_NOBELIUM = 10204;
|
||||
public const ELEMENT_OGANESSON = 10205;
|
||||
public const ELEMENT_OSMIUM = 10206;
|
||||
public const ELEMENT_OXYGEN = 10207;
|
||||
public const ELEMENT_PALLADIUM = 10208;
|
||||
public const ELEMENT_PHOSPHORUS = 10209;
|
||||
public const ELEMENT_PLATINUM = 10210;
|
||||
public const ELEMENT_PLUTONIUM = 10211;
|
||||
public const ELEMENT_POLONIUM = 10212;
|
||||
public const ELEMENT_POTASSIUM = 10213;
|
||||
public const ELEMENT_PRASEODYMIUM = 10214;
|
||||
public const ELEMENT_PROMETHIUM = 10215;
|
||||
public const ELEMENT_PROTACTINIUM = 10216;
|
||||
public const ELEMENT_RADIUM = 10217;
|
||||
public const ELEMENT_RADON = 10218;
|
||||
public const ELEMENT_RHENIUM = 10219;
|
||||
public const ELEMENT_RHODIUM = 10220;
|
||||
public const ELEMENT_ROENTGENIUM = 10221;
|
||||
public const ELEMENT_RUBIDIUM = 10222;
|
||||
public const ELEMENT_RUTHENIUM = 10223;
|
||||
public const ELEMENT_RUTHERFORDIUM = 10224;
|
||||
public const ELEMENT_SAMARIUM = 10225;
|
||||
public const ELEMENT_SCANDIUM = 10226;
|
||||
public const ELEMENT_SEABORGIUM = 10227;
|
||||
public const ELEMENT_SELENIUM = 10228;
|
||||
public const ELEMENT_SILICON = 10229;
|
||||
public const ELEMENT_SILVER = 10230;
|
||||
public const ELEMENT_SODIUM = 10231;
|
||||
public const ELEMENT_STRONTIUM = 10232;
|
||||
public const ELEMENT_SULFUR = 10233;
|
||||
public const ELEMENT_TANTALUM = 10234;
|
||||
public const ELEMENT_TECHNETIUM = 10235;
|
||||
public const ELEMENT_TELLURIUM = 10236;
|
||||
public const ELEMENT_TENNESSINE = 10237;
|
||||
public const ELEMENT_TERBIUM = 10238;
|
||||
public const ELEMENT_THALLIUM = 10239;
|
||||
public const ELEMENT_THORIUM = 10240;
|
||||
public const ELEMENT_THULIUM = 10241;
|
||||
public const ELEMENT_TIN = 10242;
|
||||
public const ELEMENT_TITANIUM = 10243;
|
||||
public const ELEMENT_TUNGSTEN = 10244;
|
||||
public const ELEMENT_URANIUM = 10245;
|
||||
public const ELEMENT_VANADIUM = 10246;
|
||||
public const ELEMENT_XENON = 10247;
|
||||
public const ELEMENT_YTTERBIUM = 10248;
|
||||
public const ELEMENT_YTTRIUM = 10249;
|
||||
public const ELEMENT_ZERO = 10250;
|
||||
public const ELEMENT_ZINC = 10251;
|
||||
public const ELEMENT_ZIRCONIUM = 10252;
|
||||
public const EMERALD = 10253;
|
||||
public const EMERALD_ORE = 10254;
|
||||
public const ENCHANTING_TABLE = 10255;
|
||||
public const END_PORTAL_FRAME = 10256;
|
||||
public const END_ROD = 10257;
|
||||
public const END_STONE = 10258;
|
||||
public const END_STONE_BRICK_SLAB = 10259;
|
||||
public const END_STONE_BRICK_STAIRS = 10260;
|
||||
public const END_STONE_BRICK_WALL = 10261;
|
||||
public const END_STONE_BRICKS = 10262;
|
||||
public const ENDER_CHEST = 10263;
|
||||
public const FAKE_WOODEN_SLAB = 10264;
|
||||
public const FARMLAND = 10265;
|
||||
public const FERN = 10266;
|
||||
public const FIRE = 10267;
|
||||
public const FLETCHING_TABLE = 10268;
|
||||
public const FLOWER_POT = 10269;
|
||||
public const FROSTED_ICE = 10270;
|
||||
public const FURNACE = 10271;
|
||||
public const GLASS = 10272;
|
||||
public const GLASS_PANE = 10273;
|
||||
public const GLOWING_OBSIDIAN = 10274;
|
||||
public const GLOWSTONE = 10275;
|
||||
public const GOLD = 10276;
|
||||
public const GOLD_ORE = 10277;
|
||||
public const GRANITE = 10278;
|
||||
public const GRANITE_SLAB = 10279;
|
||||
public const GRANITE_STAIRS = 10280;
|
||||
public const GRANITE_WALL = 10281;
|
||||
public const GRASS = 10282;
|
||||
public const GRASS_PATH = 10283;
|
||||
public const GRAVEL = 10284;
|
||||
|
||||
public const GREEN_TORCH = 10287;
|
||||
public const HARDENED_CLAY = 10288;
|
||||
public const HARDENED_GLASS = 10289;
|
||||
public const HARDENED_GLASS_PANE = 10290;
|
||||
public const HAY_BALE = 10291;
|
||||
public const HOPPER = 10292;
|
||||
public const ICE = 10293;
|
||||
public const INFESTED_CHISELED_STONE_BRICK = 10294;
|
||||
public const INFESTED_COBBLESTONE = 10295;
|
||||
public const INFESTED_CRACKED_STONE_BRICK = 10296;
|
||||
public const INFESTED_MOSSY_STONE_BRICK = 10297;
|
||||
public const INFESTED_STONE = 10298;
|
||||
public const INFESTED_STONE_BRICK = 10299;
|
||||
public const INFO_UPDATE = 10300;
|
||||
public const INFO_UPDATE2 = 10301;
|
||||
public const INVISIBLE_BEDROCK = 10302;
|
||||
public const IRON = 10303;
|
||||
public const IRON_BARS = 10304;
|
||||
public const IRON_DOOR = 10305;
|
||||
public const IRON_ORE = 10306;
|
||||
public const IRON_TRAPDOOR = 10307;
|
||||
public const ITEM_FRAME = 10308;
|
||||
public const JUKEBOX = 10309;
|
||||
public const JUNGLE_BUTTON = 10310;
|
||||
public const JUNGLE_DOOR = 10311;
|
||||
public const JUNGLE_FENCE = 10312;
|
||||
public const JUNGLE_FENCE_GATE = 10313;
|
||||
public const JUNGLE_LEAVES = 10314;
|
||||
public const JUNGLE_LOG = 10315;
|
||||
public const JUNGLE_PLANKS = 10316;
|
||||
public const JUNGLE_PRESSURE_PLATE = 10317;
|
||||
public const JUNGLE_SAPLING = 10318;
|
||||
public const JUNGLE_SIGN = 10319;
|
||||
public const JUNGLE_SLAB = 10320;
|
||||
public const JUNGLE_STAIRS = 10321;
|
||||
public const JUNGLE_TRAPDOOR = 10322;
|
||||
public const JUNGLE_WALL_SIGN = 10323;
|
||||
public const JUNGLE_WOOD = 10324;
|
||||
public const LAB_TABLE = 10325;
|
||||
public const LADDER = 10326;
|
||||
public const LANTERN = 10327;
|
||||
public const LAPIS_LAZULI = 10328;
|
||||
public const LAPIS_LAZULI_ORE = 10329;
|
||||
public const LARGE_FERN = 10330;
|
||||
public const LAVA = 10331;
|
||||
public const LECTERN = 10332;
|
||||
public const LEGACY_STONECUTTER = 10333;
|
||||
public const LEVER = 10334;
|
||||
|
||||
public const LILAC = 10337;
|
||||
public const LILY_OF_THE_VALLEY = 10338;
|
||||
public const LILY_PAD = 10339;
|
||||
|
||||
public const LIT_PUMPKIN = 10341;
|
||||
public const LOOM = 10342;
|
||||
|
||||
public const MAGMA = 10344;
|
||||
public const MATERIAL_REDUCER = 10345;
|
||||
public const MELON = 10346;
|
||||
public const MELON_STEM = 10347;
|
||||
public const MOB_HEAD = 10348;
|
||||
public const MONSTER_SPAWNER = 10349;
|
||||
public const MOSSY_COBBLESTONE = 10350;
|
||||
public const MOSSY_COBBLESTONE_SLAB = 10351;
|
||||
public const MOSSY_COBBLESTONE_STAIRS = 10352;
|
||||
public const MOSSY_COBBLESTONE_WALL = 10353;
|
||||
public const MOSSY_STONE_BRICK_SLAB = 10354;
|
||||
public const MOSSY_STONE_BRICK_STAIRS = 10355;
|
||||
public const MOSSY_STONE_BRICK_WALL = 10356;
|
||||
public const MOSSY_STONE_BRICKS = 10357;
|
||||
public const MUSHROOM_STEM = 10358;
|
||||
public const MYCELIUM = 10359;
|
||||
public const NETHER_BRICK_FENCE = 10360;
|
||||
public const NETHER_BRICK_SLAB = 10361;
|
||||
public const NETHER_BRICK_STAIRS = 10362;
|
||||
public const NETHER_BRICK_WALL = 10363;
|
||||
public const NETHER_BRICKS = 10364;
|
||||
public const NETHER_PORTAL = 10365;
|
||||
public const NETHER_QUARTZ_ORE = 10366;
|
||||
public const NETHER_REACTOR_CORE = 10367;
|
||||
public const NETHER_WART = 10368;
|
||||
public const NETHER_WART_BLOCK = 10369;
|
||||
public const NETHERRACK = 10370;
|
||||
public const NOTE_BLOCK = 10371;
|
||||
public const OAK_BUTTON = 10372;
|
||||
public const OAK_DOOR = 10373;
|
||||
public const OAK_FENCE = 10374;
|
||||
public const OAK_FENCE_GATE = 10375;
|
||||
public const OAK_LEAVES = 10376;
|
||||
public const OAK_LOG = 10377;
|
||||
public const OAK_PLANKS = 10378;
|
||||
public const OAK_PRESSURE_PLATE = 10379;
|
||||
public const OAK_SAPLING = 10380;
|
||||
public const OAK_SIGN = 10381;
|
||||
public const OAK_SLAB = 10382;
|
||||
public const OAK_STAIRS = 10383;
|
||||
public const OAK_TRAPDOOR = 10384;
|
||||
public const OAK_WALL_SIGN = 10385;
|
||||
public const OAK_WOOD = 10386;
|
||||
public const OBSIDIAN = 10387;
|
||||
|
||||
public const ORANGE_TULIP = 10389;
|
||||
public const OXEYE_DAISY = 10390;
|
||||
public const PACKED_ICE = 10391;
|
||||
public const PEONY = 10392;
|
||||
|
||||
public const PINK_TULIP = 10394;
|
||||
public const PODZOL = 10395;
|
||||
public const POLISHED_ANDESITE = 10396;
|
||||
public const POLISHED_ANDESITE_SLAB = 10397;
|
||||
public const POLISHED_ANDESITE_STAIRS = 10398;
|
||||
public const POLISHED_DIORITE = 10399;
|
||||
public const POLISHED_DIORITE_SLAB = 10400;
|
||||
public const POLISHED_DIORITE_STAIRS = 10401;
|
||||
public const POLISHED_GRANITE = 10402;
|
||||
public const POLISHED_GRANITE_SLAB = 10403;
|
||||
public const POLISHED_GRANITE_STAIRS = 10404;
|
||||
public const POPPY = 10405;
|
||||
public const POTATOES = 10406;
|
||||
public const POWERED_RAIL = 10407;
|
||||
public const PRISMARINE = 10408;
|
||||
public const PRISMARINE_BRICKS = 10409;
|
||||
public const PRISMARINE_BRICKS_SLAB = 10410;
|
||||
public const PRISMARINE_BRICKS_STAIRS = 10411;
|
||||
public const PRISMARINE_SLAB = 10412;
|
||||
public const PRISMARINE_STAIRS = 10413;
|
||||
public const PRISMARINE_WALL = 10414;
|
||||
public const PUMPKIN = 10415;
|
||||
public const PUMPKIN_STEM = 10416;
|
||||
|
||||
public const PURPLE_TORCH = 10418;
|
||||
public const PURPUR = 10419;
|
||||
public const PURPUR_PILLAR = 10420;
|
||||
public const PURPUR_SLAB = 10421;
|
||||
public const PURPUR_STAIRS = 10422;
|
||||
public const QUARTZ = 10423;
|
||||
public const QUARTZ_PILLAR = 10424;
|
||||
public const QUARTZ_SLAB = 10425;
|
||||
public const QUARTZ_STAIRS = 10426;
|
||||
public const RAIL = 10427;
|
||||
|
||||
public const RED_MUSHROOM = 10429;
|
||||
public const RED_MUSHROOM_BLOCK = 10430;
|
||||
public const RED_NETHER_BRICK_SLAB = 10431;
|
||||
public const RED_NETHER_BRICK_STAIRS = 10432;
|
||||
public const RED_NETHER_BRICK_WALL = 10433;
|
||||
public const RED_NETHER_BRICKS = 10434;
|
||||
public const RED_SAND = 10435;
|
||||
public const RED_SANDSTONE = 10436;
|
||||
public const RED_SANDSTONE_SLAB = 10437;
|
||||
public const RED_SANDSTONE_STAIRS = 10438;
|
||||
public const RED_SANDSTONE_WALL = 10439;
|
||||
public const RED_TORCH = 10440;
|
||||
public const RED_TULIP = 10441;
|
||||
public const REDSTONE = 10442;
|
||||
public const REDSTONE_COMPARATOR = 10443;
|
||||
public const REDSTONE_LAMP = 10444;
|
||||
public const REDSTONE_ORE = 10445;
|
||||
public const REDSTONE_REPEATER = 10446;
|
||||
public const REDSTONE_TORCH = 10447;
|
||||
public const REDSTONE_WIRE = 10448;
|
||||
public const RESERVED6 = 10449;
|
||||
public const ROSE_BUSH = 10450;
|
||||
public const SAND = 10451;
|
||||
public const SANDSTONE = 10452;
|
||||
public const SANDSTONE_SLAB = 10453;
|
||||
public const SANDSTONE_STAIRS = 10454;
|
||||
public const SANDSTONE_WALL = 10455;
|
||||
public const SEA_LANTERN = 10456;
|
||||
public const SEA_PICKLE = 10457;
|
||||
public const SHULKER_BOX = 10458;
|
||||
public const SLIME = 10459;
|
||||
public const SMOKER = 10460;
|
||||
public const SMOOTH_QUARTZ = 10461;
|
||||
public const SMOOTH_QUARTZ_SLAB = 10462;
|
||||
public const SMOOTH_QUARTZ_STAIRS = 10463;
|
||||
public const SMOOTH_RED_SANDSTONE = 10464;
|
||||
public const SMOOTH_RED_SANDSTONE_SLAB = 10465;
|
||||
public const SMOOTH_RED_SANDSTONE_STAIRS = 10466;
|
||||
public const SMOOTH_SANDSTONE = 10467;
|
||||
public const SMOOTH_SANDSTONE_SLAB = 10468;
|
||||
public const SMOOTH_SANDSTONE_STAIRS = 10469;
|
||||
public const SMOOTH_STONE = 10470;
|
||||
public const SMOOTH_STONE_SLAB = 10471;
|
||||
public const SNOW = 10472;
|
||||
public const SNOW_LAYER = 10473;
|
||||
public const SOUL_SAND = 10474;
|
||||
public const SPONGE = 10475;
|
||||
public const SPRUCE_BUTTON = 10476;
|
||||
public const SPRUCE_DOOR = 10477;
|
||||
public const SPRUCE_FENCE = 10478;
|
||||
public const SPRUCE_FENCE_GATE = 10479;
|
||||
public const SPRUCE_LEAVES = 10480;
|
||||
public const SPRUCE_LOG = 10481;
|
||||
public const SPRUCE_PLANKS = 10482;
|
||||
public const SPRUCE_PRESSURE_PLATE = 10483;
|
||||
public const SPRUCE_SAPLING = 10484;
|
||||
public const SPRUCE_SIGN = 10485;
|
||||
public const SPRUCE_SLAB = 10486;
|
||||
public const SPRUCE_STAIRS = 10487;
|
||||
public const SPRUCE_TRAPDOOR = 10488;
|
||||
public const SPRUCE_WALL_SIGN = 10489;
|
||||
public const SPRUCE_WOOD = 10490;
|
||||
public const STAINED_CLAY = 10491;
|
||||
public const STAINED_GLASS = 10492;
|
||||
public const STAINED_GLASS_PANE = 10493;
|
||||
public const STAINED_HARDENED_GLASS = 10494;
|
||||
public const STAINED_HARDENED_GLASS_PANE = 10495;
|
||||
public const STONE = 10496;
|
||||
public const STONE_BRICK_SLAB = 10497;
|
||||
public const STONE_BRICK_STAIRS = 10498;
|
||||
public const STONE_BRICK_WALL = 10499;
|
||||
public const STONE_BRICKS = 10500;
|
||||
public const STONE_BUTTON = 10501;
|
||||
public const STONE_PRESSURE_PLATE = 10502;
|
||||
public const STONE_SLAB = 10503;
|
||||
public const STONE_STAIRS = 10504;
|
||||
public const STONECUTTER = 10505;
|
||||
|
||||
public const SUGARCANE = 10518;
|
||||
public const SUNFLOWER = 10519;
|
||||
public const SWEET_BERRY_BUSH = 10520;
|
||||
public const TALL_GRASS = 10521;
|
||||
public const TNT = 10522;
|
||||
public const TORCH = 10523;
|
||||
public const TRAPPED_CHEST = 10524;
|
||||
public const TRIPWIRE = 10525;
|
||||
public const TRIPWIRE_HOOK = 10526;
|
||||
public const UNDERWATER_TORCH = 10527;
|
||||
public const VINES = 10528;
|
||||
public const WALL_BANNER = 10529;
|
||||
public const WALL_CORAL_FAN = 10530;
|
||||
public const WATER = 10531;
|
||||
public const WEIGHTED_PRESSURE_PLATE_HEAVY = 10532;
|
||||
public const WEIGHTED_PRESSURE_PLATE_LIGHT = 10533;
|
||||
public const WHEAT = 10534;
|
||||
|
||||
public const WHITE_TULIP = 10536;
|
||||
public const WOOL = 10537;
|
||||
|
||||
public const GLAZED_TERRACOTTA = 10539;
|
||||
public const AMETHYST = 10540;
|
||||
public const ANCIENT_DEBRIS = 10541;
|
||||
public const BASALT = 10542;
|
||||
public const POLISHED_BASALT = 10543;
|
||||
public const SMOOTH_BASALT = 10544;
|
||||
public const BLACKSTONE = 10545;
|
||||
public const BLACKSTONE_SLAB = 10546;
|
||||
public const BLACKSTONE_STAIRS = 10547;
|
||||
public const BLACKSTONE_WALL = 10548;
|
||||
public const POLISHED_BLACKSTONE = 10549;
|
||||
public const POLISHED_BLACKSTONE_BUTTON = 10550;
|
||||
public const POLISHED_BLACKSTONE_PRESSURE_PLATE = 10551;
|
||||
public const POLISHED_BLACKSTONE_SLAB = 10552;
|
||||
public const POLISHED_BLACKSTONE_STAIRS = 10553;
|
||||
public const POLISHED_BLACKSTONE_WALL = 10554;
|
||||
public const CHISELED_POLISHED_BLACKSTONE = 10555;
|
||||
public const POLISHED_BLACKSTONE_BRICKS = 10556;
|
||||
public const POLISHED_BLACKSTONE_BRICK_SLAB = 10557;
|
||||
public const POLISHED_BLACKSTONE_BRICK_STAIRS = 10558;
|
||||
public const POLISHED_BLACKSTONE_BRICK_WALL = 10559;
|
||||
public const CRACKED_POLISHED_BLACKSTONE_BRICKS = 10560;
|
||||
public const LIGHT = 10561;
|
||||
public const RAW_COPPER = 10562;
|
||||
public const RAW_GOLD = 10563;
|
||||
public const RAW_IRON = 10564;
|
||||
public const CALCITE = 10565;
|
||||
public const DEEPSLATE = 10566;
|
||||
public const DEEPSLATE_BRICKS = 10567;
|
||||
public const DEEPSLATE_BRICK_SLAB = 10568;
|
||||
public const DEEPSLATE_BRICK_STAIRS = 10569;
|
||||
public const DEEPSLATE_BRICK_WALL = 10570;
|
||||
public const CRACKED_DEEPSLATE_BRICKS = 10571;
|
||||
public const DEEPSLATE_TILES = 10572;
|
||||
public const DEEPSLATE_TILE_SLAB = 10573;
|
||||
public const DEEPSLATE_TILE_STAIRS = 10574;
|
||||
public const DEEPSLATE_TILE_WALL = 10575;
|
||||
public const CRACKED_DEEPSLATE_TILES = 10576;
|
||||
public const COBBLED_DEEPSLATE = 10577;
|
||||
public const COBBLED_DEEPSLATE_SLAB = 10578;
|
||||
public const COBBLED_DEEPSLATE_STAIRS = 10579;
|
||||
public const COBBLED_DEEPSLATE_WALL = 10580;
|
||||
public const POLISHED_DEEPSLATE = 10581;
|
||||
public const POLISHED_DEEPSLATE_SLAB = 10582;
|
||||
public const POLISHED_DEEPSLATE_STAIRS = 10583;
|
||||
public const POLISHED_DEEPSLATE_WALL = 10584;
|
||||
public const QUARTZ_BRICKS = 10585;
|
||||
public const CHISELED_DEEPSLATE = 10586;
|
||||
public const CHISELED_NETHER_BRICKS = 10587;
|
||||
public const CRACKED_NETHER_BRICKS = 10588;
|
||||
public const TUFF = 10589;
|
||||
public const SOUL_TORCH = 10590;
|
||||
public const SOUL_LANTERN = 10591;
|
||||
public const SOUL_SOIL = 10592;
|
||||
public const SOUL_FIRE = 10593;
|
||||
public const SHROOMLIGHT = 10594;
|
||||
public const MANGROVE_PLANKS = 10595;
|
||||
public const CRIMSON_PLANKS = 10596;
|
||||
public const WARPED_PLANKS = 10597;
|
||||
public const MANGROVE_FENCE = 10598;
|
||||
public const CRIMSON_FENCE = 10599;
|
||||
public const WARPED_FENCE = 10600;
|
||||
public const MANGROVE_SLAB = 10601;
|
||||
public const CRIMSON_SLAB = 10602;
|
||||
public const WARPED_SLAB = 10603;
|
||||
public const MANGROVE_LOG = 10604;
|
||||
public const CRIMSON_STEM = 10605;
|
||||
public const WARPED_STEM = 10606;
|
||||
public const MANGROVE_WOOD = 10607;
|
||||
public const CRIMSON_HYPHAE = 10608;
|
||||
public const WARPED_HYPHAE = 10609;
|
||||
public const MANGROVE_TRAPDOOR = 10610;
|
||||
public const CRIMSON_TRAPDOOR = 10611;
|
||||
public const WARPED_TRAPDOOR = 10612;
|
||||
public const MANGROVE_BUTTON = 10613;
|
||||
public const CRIMSON_BUTTON = 10614;
|
||||
public const WARPED_BUTTON = 10615;
|
||||
public const MANGROVE_PRESSURE_PLATE = 10616;
|
||||
public const CRIMSON_PRESSURE_PLATE = 10617;
|
||||
public const WARPED_PRESSURE_PLATE = 10618;
|
||||
public const MANGROVE_DOOR = 10619;
|
||||
public const CRIMSON_DOOR = 10620;
|
||||
public const WARPED_DOOR = 10621;
|
||||
public const MANGROVE_FENCE_GATE = 10622;
|
||||
public const CRIMSON_FENCE_GATE = 10623;
|
||||
public const WARPED_FENCE_GATE = 10624;
|
||||
public const MANGROVE_STAIRS = 10625;
|
||||
public const CRIMSON_STAIRS = 10626;
|
||||
public const WARPED_STAIRS = 10627;
|
||||
public const MANGROVE_SIGN = 10628;
|
||||
public const CRIMSON_SIGN = 10629;
|
||||
public const WARPED_SIGN = 10630;
|
||||
public const MANGROVE_WALL_SIGN = 10631;
|
||||
public const CRIMSON_WALL_SIGN = 10632;
|
||||
public const WARPED_WALL_SIGN = 10633;
|
||||
public const TINTED_GLASS = 10634;
|
||||
public const HONEYCOMB = 10635;
|
||||
public const DEEPSLATE_COAL_ORE = 10636;
|
||||
public const DEEPSLATE_DIAMOND_ORE = 10637;
|
||||
public const DEEPSLATE_EMERALD_ORE = 10638;
|
||||
public const DEEPSLATE_LAPIS_LAZULI_ORE = 10639;
|
||||
public const DEEPSLATE_REDSTONE_ORE = 10640;
|
||||
public const DEEPSLATE_IRON_ORE = 10641;
|
||||
public const DEEPSLATE_GOLD_ORE = 10642;
|
||||
public const DEEPSLATE_COPPER_ORE = 10643;
|
||||
public const COPPER_ORE = 10644;
|
||||
public const NETHER_GOLD_ORE = 10645;
|
||||
public const MUD = 10646;
|
||||
public const MUD_BRICKS = 10647;
|
||||
public const MUD_BRICK_SLAB = 10648;
|
||||
public const MUD_BRICK_STAIRS = 10649;
|
||||
public const MUD_BRICK_WALL = 10650;
|
||||
public const PACKED_MUD = 10651;
|
||||
public const WARPED_WART_BLOCK = 10652;
|
||||
public const CRYING_OBSIDIAN = 10653;
|
||||
public const GILDED_BLACKSTONE = 10654;
|
||||
public const LIGHTNING_ROD = 10655;
|
||||
public const COPPER = 10656;
|
||||
public const CUT_COPPER = 10657;
|
||||
public const CUT_COPPER_SLAB = 10658;
|
||||
public const CUT_COPPER_STAIRS = 10659;
|
||||
public const CANDLE = 10660;
|
||||
public const DYED_CANDLE = 10661;
|
||||
public const CAKE_WITH_CANDLE = 10662;
|
||||
public const CAKE_WITH_DYED_CANDLE = 10663;
|
||||
public const WITHER_ROSE = 10664;
|
||||
public const HANGING_ROOTS = 10665;
|
||||
public const CARTOGRAPHY_TABLE = 10666;
|
||||
public const SMITHING_TABLE = 10667;
|
||||
public const NETHERITE = 10668;
|
||||
public const SPORE_BLOSSOM = 10669;
|
||||
public const CAULDRON = 10670;
|
||||
public const WATER_CAULDRON = 10671;
|
||||
public const LAVA_CAULDRON = 10672;
|
||||
public const POTION_CAULDRON = 10673;
|
||||
public const POWDER_SNOW_CAULDRON = 10674;
|
||||
public const CHORUS_FLOWER = 10675;
|
||||
public const CHORUS_PLANT = 10676;
|
||||
public const MANGROVE_ROOTS = 10677;
|
||||
public const MUDDY_MANGROVE_ROOTS = 10678;
|
||||
public const FROGLIGHT = 10679;
|
||||
public const TWISTING_VINES = 10680;
|
||||
public const WEEPING_VINES = 10681;
|
||||
public const CHAIN = 10682;
|
||||
public const SCULK = 10683;
|
||||
public const GLOWING_ITEM_FRAME = 10684;
|
||||
public const MANGROVE_LEAVES = 10685;
|
||||
public const AZALEA_LEAVES = 10686;
|
||||
public const FLOWERING_AZALEA_LEAVES = 10687;
|
||||
public const REINFORCED_DEEPSLATE = 10688;
|
||||
public const CAVE_VINES = 10689;
|
||||
|
||||
public const FIRST_UNUSED_BLOCK_ID = 10690;
|
||||
|
||||
private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID;
|
||||
|
||||
/**
|
||||
* Returns a new runtime block type ID, e.g. for use by a custom block.
|
||||
*/
|
||||
public static function newId() : int{
|
||||
return self::$nextDynamicId++;
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use function array_fill_keys;
|
||||
use function array_keys;
|
||||
|
||||
final class BlockTypeInfo{
|
||||
/**
|
||||
* @var true[]
|
||||
* @phpstan-var array<string, true>
|
||||
*/
|
||||
private array $typeTags;
|
||||
|
||||
/**
|
||||
* @param string[] $typeTags
|
||||
*/
|
||||
public function __construct(
|
||||
private BlockBreakInfo $breakInfo,
|
||||
array $typeTags = []
|
||||
){
|
||||
$this->typeTags = array_fill_keys($typeTags, true);
|
||||
}
|
||||
|
||||
public function getBreakInfo() : BlockBreakInfo{ return $this->breakInfo; }
|
||||
|
||||
/** @return string[] */
|
||||
public function getTypeTags() : array{ return array_keys($this->typeTags); }
|
||||
|
||||
public function hasTypeTag(string $tag) : bool{ return isset($this->typeTags[$tag]); }
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
final class BlockTypeTags{
|
||||
private const PREFIX = "pocketmine:";
|
||||
|
||||
public const DIRT = self::PREFIX . "dirt";
|
||||
public const MUD = self::PREFIX . "mud";
|
||||
public const SAND = self::PREFIX . "sand";
|
||||
public const POTTABLE_PLANTS = self::PREFIX . "pottable";
|
||||
public const FIRE = self::PREFIX . "fire";
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user