mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-21 00:07:30 +00:00
merge remote tracking upstream
This commit is contained in:
commit
d6b7a9ed45
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@ -3,7 +3,7 @@ updates:
|
||||
- package-ecosystem: composer
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
interval: weekly
|
||||
time: "10:00"
|
||||
open-pull-requests-limit: 10
|
||||
ignore:
|
||||
@ -21,4 +21,4 @@ updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
interval: weekly
|
||||
|
8
.github/workflows/build-docker-image.yml
vendored
8
.github/workflows/build-docker-image.yml
vendored
@ -53,7 +53,7 @@ jobs:
|
||||
run: echo NAME=$(echo "${GITHUB_REPOSITORY,,}") >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build image for tag
|
||||
uses: docker/build-push-action@v5.0.0
|
||||
uses: docker/build-push-action@v5.1.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
@ -66,7 +66,7 @@ jobs:
|
||||
|
||||
- name: Build image for major tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v5.0.0
|
||||
uses: docker/build-push-action@v5.1.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
@ -79,7 +79,7 @@ jobs:
|
||||
|
||||
- name: Build image for minor tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v5.0.0
|
||||
uses: docker/build-push-action@v5.1.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
@ -92,7 +92,7 @@ jobs:
|
||||
|
||||
- name: Build image for latest tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v5.0.0
|
||||
uses: docker/build-push-action@v5.1.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
|
2
.github/workflows/discord-release-notify.yml
vendored
2
.github/workflows/discord-release-notify.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.27.1
|
||||
uses: shivammathur/setup-php@2.28.0
|
||||
with:
|
||||
php-version: 8.2
|
||||
|
||||
|
4
.github/workflows/draft-release.yml
vendored
4
.github/workflows/draft-release.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@2.27.1
|
||||
uses: shivammathur/setup-php@2.28.0
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
|
||||
@ -77,7 +77,7 @@ jobs:
|
||||
> build_info.json
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release_artifacts
|
||||
path: |
|
||||
|
165
.github/workflows/main-php-matrix.yml
vendored
Normal file
165
.github/workflows/main-php-matrix.yml
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
name: CI (all supported PHP versions)
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
php:
|
||||
description: 'PHP version in X.Y format'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
#these are parameterized to ease updating
|
||||
pm-version-major:
|
||||
description: 'PocketMine-MP major version'
|
||||
default: 5
|
||||
type: number
|
||||
image:
|
||||
description: 'Runner image to use'
|
||||
default: 'ubuntu-20.04'
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
phpstan:
|
||||
name: PHPStan analysis
|
||||
runs-on: ${{ inputs.image }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ inputs.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: ${{ inputs.pm-version-major }}
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ inputs.php }}-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --prefer-dist --no-interaction
|
||||
|
||||
- name: Run PHPStan
|
||||
run: ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
|
||||
|
||||
phpunit:
|
||||
name: PHPUnit tests
|
||||
runs-on: ${{ inputs.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ inputs.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: ${{ inputs.pm-version-major }}
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ inputs.php }}-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer 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
|
||||
runs-on: ${{ inputs.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ inputs.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: ${{ inputs.pm-version-major }}
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ inputs.php }}-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-dev --prefer-dist --no-interaction
|
||||
|
||||
- name: Run integration tests
|
||||
run: ./tests/travis.sh -t4
|
||||
|
||||
codegen:
|
||||
name: Generated Code consistency checks
|
||||
runs-on: ${{ inputs.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ inputs.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: ${{ inputs.pm-version-major }}
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ inputs.php }}-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer 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 BedrockData available files constants
|
||||
run: php build/generate-bedrockdata-path-consts.php
|
||||
|
||||
- name: Regenerate YmlServerProperties constants
|
||||
run: php build/generate-pocketmine-yml-property-consts.php
|
||||
|
||||
- name: Verify code is unchanged
|
||||
run: |
|
||||
git diff
|
||||
git diff --quiet
|
161
.github/workflows/main.yml
vendored
161
.github/workflows/main.yml
vendored
@ -6,162 +6,17 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
phpstan:
|
||||
name: PHPStan analysis
|
||||
runs-on: ${{ matrix.image }}
|
||||
|
||||
all-php-versions:
|
||||
name: PHP ${{ matrix.php }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: ["8.1", "8.2"]
|
||||
php: ["8.1", "8.2", "8.3"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "5"
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --prefer-dist --no-interaction
|
||||
|
||||
- name: Run PHPStan
|
||||
run: ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
|
||||
|
||||
phpunit:
|
||||
name: PHPUnit tests
|
||||
runs-on: ${{ matrix.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "5"
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer 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
|
||||
runs-on: ${{ matrix.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "5"
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-dev --prefer-dist --no-interaction
|
||||
|
||||
- name: Run integration tests
|
||||
run: ./tests/travis.sh -t4
|
||||
|
||||
codegen:
|
||||
name: Generated Code consistency checks
|
||||
runs-on: ${{ matrix.image }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
install-path: "./bin"
|
||||
pm-version-major: "5"
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer 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 BedrockData available files constants
|
||||
run: php build/generate-bedrockdata-path-consts.php
|
||||
|
||||
- name: Regenerate YmlServerProperties constants
|
||||
run: php build/generate-pocketmine-yml-property-consts.php
|
||||
|
||||
- name: Verify code is unchanged
|
||||
run: |
|
||||
git diff
|
||||
git diff --quiet
|
||||
uses: ./.github/workflows/main-php-matrix.yml
|
||||
with:
|
||||
php: ${{ matrix.php }}
|
||||
secrets: inherit
|
||||
|
||||
codestyle:
|
||||
name: Code Style checks
|
||||
@ -173,7 +28,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.27.1
|
||||
uses: shivammathur/setup-php@2.28.0
|
||||
with:
|
||||
php-version: 8.2
|
||||
tools: php-cs-fixer:3.38
|
||||
|
2
.github/workflows/support.yml
vendored
2
.github/workflows/support.yml
vendored
@ -8,7 +8,7 @@ jobs:
|
||||
support:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/support-requests@v3
|
||||
- uses: dessant/support-requests@v4
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
support-label: "Support request"
|
||||
|
46
README.md
46
README.md
@ -20,31 +20,61 @@
|
||||
<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
|
||||
## What is this?
|
||||
PocketMine-MP is a highly customisable server software for Minecraft: Bedrock Edition, built from scratch in PHP, with over 10 years of history.
|
||||
|
||||
If you're looking to create a Minecraft: Bedrock server with **custom functionality**, look no further.
|
||||
|
||||
- 🧩 **Powerful plugin API** - extend and customise gameplay as you see fit
|
||||
- 🗺️ **Rich ecosystem** and **large developer community** - find plugins easily and learn to develop your own
|
||||
- 🌐 **Multi-world support** - offer a more varied game experience to players without transferring them to other server nodes
|
||||
- 🏎️ **Performance** - get 100+ players onto one server (depending on hardware and plugins)
|
||||
- ⤴️ **Continuously updated** - new Minecraft versions are usually supported within days
|
||||
|
||||
## :x: PocketMine-MP is NOT a vanilla Minecraft server software.
|
||||
**It is poorly suited to hosting vanilla survival servers.**
|
||||
It doesn't have many features from the vanilla game, such as vanilla world generation, redstone, mob AI, and various other things.
|
||||
|
||||
If you just want to play **vanilla survival multiplayer**, consider using the [official Minecraft: Bedrock server software](https://minecraft.net/download/server/bedrock) instead of PocketMine-MP.
|
||||
|
||||
If that's not an option for you, you may be able to add some of PocketMine-MP's missing features using plugins from [Poggit](https://poggit.pmmp.io/plugins), or write plugins to implement them yourself.
|
||||
|
||||
## 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)
|
||||
- [Plugin repository](https://poggit.pmmp.io/plugins)
|
||||
|
||||
## Community & Support
|
||||
- [Forums](https://forums.pmmp.io/)
|
||||
- [Discord](https://discord.gg/bmSAZBG)
|
||||
- [StackOverflow](https://stackoverflow.com/tags/pocketmine)
|
||||
Join our [Discord](https://discord.gg/bmSAZBG) server to chat with other users and developers.
|
||||
|
||||
You can also post questions on [StackOverflow](https://stackoverflow.com/tags/pocketmine) under the tag `pocketmine`.
|
||||
|
||||
## Developing Plugins
|
||||
If you want to write your own plugins, the following resources may be useful.
|
||||
Don't forget you can always ask our community if you need help.
|
||||
|
||||
## 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
|
||||
* [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 to PocketMine-MP
|
||||
PocketMine-MP accepts community contributions! The following resources will be useful if you want to contribute to PocketMine-MP.
|
||||
* [Building and running PocketMine-MP from source](BUILDING.md)
|
||||
* [Contributing Guidelines](CONTRIBUTING.md)
|
||||
|
||||
## Donate
|
||||
- Bitcoin Cash (BCH): `qq3r46hn6ljnhnqnfwxt5pg3g447eq9jhvw5ddfear`
|
||||
PocketMine-MP is free, but it requires a lot of time and effort from unpaid volunteers to develop. Donations enable us to keep delivering support for new versions and adding features your players love.
|
||||
|
||||
You can support development using the following methods:
|
||||
|
||||
- [Patreon](https://www.patreon.com/pocketminemp)
|
||||
- Bitcoin (BTC): `171u8K9e4FtU6j3e5sqNoxKUgEw9qWQdRV`
|
||||
- Stellar Lumens (XLM): `GAAC5WZ33HCTE3BFJFZJXONMEIBNHFLBXM2HJVAZHXXPYA3HP5XPPS7T`
|
||||
- [Patreon](https://www.patreon.com/pocketminemp)
|
||||
|
||||
Thanks for your support!
|
||||
|
||||
## Licensing information
|
||||
This project is licensed under LGPL-3.0. Please see the [LICENSE](/LICENSE) file for details.
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 39885cf24826773bc3a0e8134e04a2032e97f477
|
||||
Subproject commit 6f619bf7a0b00e72a7c90915eec6e5a28866aa55
|
@ -32,6 +32,7 @@ use function getcwd;
|
||||
use function getopt;
|
||||
use function implode;
|
||||
use function ini_get;
|
||||
use function is_string;
|
||||
use function microtime;
|
||||
use function preg_quote;
|
||||
use function realpath;
|
||||
@ -147,8 +148,17 @@ function main() : void{
|
||||
}else{
|
||||
$build = 0;
|
||||
}
|
||||
if(isset($opts["out"])){
|
||||
if(!is_string($opts["out"])){
|
||||
echo "--out cannot be specified multiple times" . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
$pharPath = $opts["out"];
|
||||
}else{
|
||||
$pharPath = getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar";
|
||||
}
|
||||
foreach(buildPhar(
|
||||
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
|
||||
$pharPath,
|
||||
dirname(__DIR__) . DIRECTORY_SEPARATOR,
|
||||
[
|
||||
'resources',
|
||||
|
16
changelogs/4.26.md
Normal file
16
changelogs/4.26.md
Normal file
@ -0,0 +1,16 @@
|
||||
# 4.26.0
|
||||
Released 6th December 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.50**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.20.50.
|
||||
|
||||
**Plugin compatibility:** Plugins for previous 4.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` namespace.
|
||||
Do not update plugin minimum API versions unless you need new features added in this release.
|
||||
|
||||
**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.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.20.50.
|
||||
- Removed support for older versions.
|
46
changelogs/5.10.md
Normal file
46
changelogs/5.10.md
Normal file
@ -0,0 +1,46 @@
|
||||
# 5.10.0
|
||||
Released 14th December 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.50**
|
||||
|
||||
This is a minor feature release, including new gameplay features and minor performance improvements.
|
||||
|
||||
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
|
||||
Do not update plugin minimum API versions unless you need new features added in this release.
|
||||
|
||||
**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.
|
||||
|
||||
## General
|
||||
- PHP 8.2 is now used by default. PHP 8.1 is still supported, but will be removed in a future 5.x release.
|
||||
- Improved timings reports by removing `Breakdown` timings group. This group serves no purpose with tree timings and made for confusing reading.
|
||||
|
||||
## Performance
|
||||
- Improved performance of `Block::encodeFullState()` in most conditions. This in turn improves performance of `World::setBlock()` and `World::setBlockAt()`.
|
||||
- Improved network compression performance by avoiding unnecessary object allocations.
|
||||
- Timings now report time spent in individual `Snooze` handlers, making it easier to debug performance issues.
|
||||
|
||||
## Gameplay
|
||||
### Blocks
|
||||
- Implemented crop growth speed modifiers.
|
||||
- The following things now positively affect crop growth speed:
|
||||
- Being planted on or being adjacent to farmland (hydrated farmland offers a larger benefit than dry farmland)
|
||||
- Potential light level of at least 9
|
||||
- Being planted in rows with space between them (or a different type of crop)
|
||||
- The following things now negatively affect crop growth speed:
|
||||
- Improper arrangement (e.g. the same crop on all sides)
|
||||
- Insufficient light level (below 9)
|
||||
- Poorly arranged crops will grow slower in this version. Past versions behaved as if crops were always planted in ideal conditions.
|
||||
- Crops planted in ideal conditions will grow at the same speed as before.
|
||||
|
||||
### Items
|
||||
- Added the following new items:
|
||||
- All types of Smithing Template
|
||||
- Pitcher Pod is now correctly registered. In previous versions, it was mapped to the Pitcher Crop block, causing incorrect name display in commands.
|
||||
|
||||
## Internals
|
||||
- Cleaned up various getter usages where direct property access is possible.
|
||||
- Avoided unnecessary repeated getter calls in some loops.
|
||||
- `NetworkSession` may now track `string` instead of `CompressBatchPromise` when a batch was synchronously compressed. This significantly reduces object allocations and improves performance.
|
||||
- `NetworkSession` now sends less information to clients on login validation failure. This avoids leaking potentially sensitive error information to clients.
|
||||
- Clients can correlate their disconnects with server-side logs using the `Error ID` shown on the disconnect screen.
|
30
changelogs/5.9.md
Normal file
30
changelogs/5.9.md
Normal file
@ -0,0 +1,30 @@
|
||||
# 5.9.0
|
||||
Released 6th December 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.50**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.20.50.
|
||||
|
||||
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
|
||||
Do not update plugin minimum API versions unless you need new features added in this release.
|
||||
|
||||
**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.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.20.50.
|
||||
- Removed support for older versions.
|
||||
|
||||
## Fixes
|
||||
- Fixed `pitcher_plant` and `pitcher_pod` not being accepted by `StringToItemParser` (and therefore not being usable in commands).
|
||||
- Rotation of items in item frames in worlds from newer versions of Bedrock is now correctly loaded.
|
||||
- Fixed possible crash in block update sending if a chunk was unloaded during a previous chunk's block update syncing.
|
||||
- Fixed `AsyncTask::fetchLocal()` throwing an exception if `null` was stored in the local storage.
|
||||
|
||||
## Documentation
|
||||
- `Server::prepareBatch()` is now correctly marked as `@internal`.
|
||||
- Updated documentation for `Server::prepareBatch()` to accurately reflect its behaviour.
|
||||
- Fixed incorrect path in doc comments of `EnumTrait` and `RegistryTrait`.
|
||||
|
||||
## Internals
|
||||
- Added PHP 8.3 to the test matrix. This has not been thoroughly tested yet, so it should only be used for testing purposes.
|
@ -33,10 +33,10 @@
|
||||
"composer-runtime-api": "^2.0",
|
||||
"adhocore/json-comment": "~1.2.0",
|
||||
"pocketmine/netresearch-jsonmapper": "~v4.2.1000",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~3.3.0+bedrock-1.20.40",
|
||||
"pocketmine/bedrock-data": "~2.6.0+bedrock-1.20.40",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "~1.5.0+bedrock-1.20.30",
|
||||
"pocketmine/bedrock-protocol": "~25.0.0+bedrock-1.20.40",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~3.4.0+bedrock-1.20.50",
|
||||
"pocketmine/bedrock-data": "~2.7.0+bedrock-1.20.50",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "~1.6.0+bedrock-1.20.50",
|
||||
"pocketmine/bedrock-protocol": "~26.0.0+bedrock-1.20.50",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/color": "^0.3.0",
|
||||
@ -49,10 +49,10 @@
|
||||
"pocketmine/raklib-ipc": "^0.2.0",
|
||||
"pocketmine/snooze": "^0.5.0",
|
||||
"ramsey/uuid": "~4.7.0",
|
||||
"symfony/filesystem": "~6.3.0"
|
||||
"symfony/filesystem": "~6.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.10.41",
|
||||
"phpstan/phpstan": "1.10.55",
|
||||
"phpstan/phpstan-phpunit": "^1.1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.2.0",
|
||||
"phpunit/phpunit": "~10.3.0 || ~10.2.0 || ~10.1.0"
|
||||
|
178
composer.lock
generated
178
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "5c19f4766fd04be0cbd38d9f4681864e",
|
||||
"content-hash": "d7a3fceea557add1b8cb461554db1ee7",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -122,16 +122,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-block-upgrade-schema",
|
||||
"version": "3.3.0",
|
||||
"version": "3.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git",
|
||||
"reference": "ee46b9367af262bbddd9f122d4d5b5b495b892e7"
|
||||
"reference": "9872eb37f15080b19c2b7861085e549c48dda92d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/ee46b9367af262bbddd9f122d4d5b5b495b892e7",
|
||||
"reference": "ee46b9367af262bbddd9f122d4d5b5b495b892e7",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/9872eb37f15080b19c2b7861085e549c48dda92d",
|
||||
"reference": "9872eb37f15080b19c2b7861085e549c48dda92d",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -142,22 +142,22 @@
|
||||
"description": "Schemas describing how to upgrade saved block data in older Minecraft: Bedrock Edition world saves",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockBlockUpgradeSchema/issues",
|
||||
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/3.3.0"
|
||||
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/3.4.0"
|
||||
},
|
||||
"time": "2023-10-16T16:11:02+00:00"
|
||||
"time": "2023-11-08T15:22:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-data",
|
||||
"version": "2.6.0+bedrock-1.20.40",
|
||||
"version": "2.7.0+bedrock-1.20.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockData.git",
|
||||
"reference": "37e780d28b470230bda3579b04cb50d406e3fbe6"
|
||||
"reference": "36f975dfca7520b7d36b0b39429f274464c9bc13"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/37e780d28b470230bda3579b04cb50d406e3fbe6",
|
||||
"reference": "37e780d28b470230bda3579b04cb50d406e3fbe6",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/36f975dfca7520b7d36b0b39429f274464c9bc13",
|
||||
"reference": "36f975dfca7520b7d36b0b39429f274464c9bc13",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -168,22 +168,22 @@
|
||||
"description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockData/issues",
|
||||
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.20.40"
|
||||
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.20.50"
|
||||
},
|
||||
"time": "2023-10-26T10:39:13+00:00"
|
||||
"time": "2023-12-06T13:59:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-item-upgrade-schema",
|
||||
"version": "1.5.0",
|
||||
"version": "1.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git",
|
||||
"reference": "3edc9ebbad9a4f2d9c8f53b3a5ba44d4a792ad93"
|
||||
"reference": "d374e5fd8302977675dcd2a42733abd3ee476ca1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/3edc9ebbad9a4f2d9c8f53b3a5ba44d4a792ad93",
|
||||
"reference": "3edc9ebbad9a4f2d9c8f53b3a5ba44d4a792ad93",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/d374e5fd8302977675dcd2a42733abd3ee476ca1",
|
||||
"reference": "d374e5fd8302977675dcd2a42733abd3ee476ca1",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -194,22 +194,22 @@
|
||||
"description": "JSON schemas for upgrading items found in older Minecraft: Bedrock world saves",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockItemUpgradeSchema/issues",
|
||||
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.5.0"
|
||||
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.6.0"
|
||||
},
|
||||
"time": "2023-09-01T19:58:57+00:00"
|
||||
"time": "2023-11-08T18:12:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-protocol",
|
||||
"version": "25.0.0+bedrock-1.20.40",
|
||||
"version": "26.0.0+bedrock-1.20.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockProtocol.git",
|
||||
"reference": "69c36c96f6835e93fc278071aa2bb9829abe5cf8"
|
||||
"reference": "f278a0b6d4fa1e2e0408a125f323a3118b1968df"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/69c36c96f6835e93fc278071aa2bb9829abe5cf8",
|
||||
"reference": "69c36c96f6835e93fc278071aa2bb9829abe5cf8",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/f278a0b6d4fa1e2e0408a125f323a3118b1968df",
|
||||
"reference": "f278a0b6d4fa1e2e0408a125f323a3118b1968df",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -223,10 +223,10 @@
|
||||
"ramsey/uuid": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.10.33",
|
||||
"phpstan/phpstan": "1.10.39",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0.0",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
"phpunit/phpunit": "^9.5 || ^10.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@ -241,9 +241,9 @@
|
||||
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/25.0.0+bedrock-1.20.40"
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/26.0.0+bedrock-1.20.50"
|
||||
},
|
||||
"time": "2023-10-26T11:03:10+00:00"
|
||||
"time": "2023-12-06T14:08:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
@ -830,16 +830,16 @@
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"version": "4.7.4",
|
||||
"version": "4.7.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/uuid.git",
|
||||
"reference": "60a4c63ab724854332900504274f6150ff26d286"
|
||||
"reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/60a4c63ab724854332900504274f6150ff26d286",
|
||||
"reference": "60a4c63ab724854332900504274f6150ff26d286",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
|
||||
"reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -906,7 +906,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/uuid/issues",
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.7.4"
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.7.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -918,20 +918,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-04-15T23:01:58+00:00"
|
||||
"time": "2023-11-08T05:53:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v6.3.1",
|
||||
"version": "v6.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae"
|
||||
"reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
|
||||
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59",
|
||||
"reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -965,7 +965,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v6.3.1"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v6.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -981,7 +981,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-06-01T08:30:39+00:00"
|
||||
"time": "2023-07-26T17:27:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
@ -1211,25 +1211,27 @@
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.17.1",
|
||||
"version": "v5.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d"
|
||||
"reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
|
||||
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4a21235f7e56e713259a6f76bf4b5ea08502b9dc",
|
||||
"reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-json": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"php": ">=7.0"
|
||||
"php": ">=7.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"ircmaxell/php-yacc": "^0.0.7",
|
||||
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"bin": [
|
||||
"bin/php-parse"
|
||||
@ -1237,7 +1239,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.9-dev"
|
||||
"dev-master": "5.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -1261,9 +1263,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.0.0"
|
||||
},
|
||||
"time": "2023-08-13T19:53:39+00:00"
|
||||
"time": "2024-01-07T17:17:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
@ -1378,16 +1380,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.10.41",
|
||||
"version": "1.10.55",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "c6174523c2a69231df55bdc65b61655e72876d76"
|
||||
"reference": "9a88f9d18ddf4cf54c922fbeac16c4cb164c5949"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/c6174523c2a69231df55bdc65b61655e72876d76",
|
||||
"reference": "c6174523c2a69231df55bdc65b61655e72876d76",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/9a88f9d18ddf4cf54c922fbeac16c4cb164c5949",
|
||||
"reference": "9a88f9d18ddf4cf54c922fbeac16c4cb164c5949",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1436,7 +1438,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-11-05T12:57:57+00:00"
|
||||
"time": "2024-01-08T12:32:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-phpunit",
|
||||
@ -1541,23 +1543,23 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "10.1.7",
|
||||
"version": "10.1.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "355324ca4980b8916c18b9db29f3ef484078f26e"
|
||||
"reference": "78c3b7625965c2513ee96569a4dbb62601784145"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/355324ca4980b8916c18b9db29f3ef484078f26e",
|
||||
"reference": "355324ca4980b8916c18b9db29f3ef484078f26e",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/78c3b7625965c2513ee96569a4dbb62601784145",
|
||||
"reference": "78c3b7625965c2513ee96569a4dbb62601784145",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"nikic/php-parser": "^4.15",
|
||||
"nikic/php-parser": "^4.18 || ^5.0",
|
||||
"php": ">=8.1",
|
||||
"phpunit/php-file-iterator": "^4.0",
|
||||
"phpunit/php-text-template": "^3.0",
|
||||
@ -1607,7 +1609,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.7"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.11"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1615,7 +1617,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-10-04T15:34:17+00:00"
|
||||
"time": "2023-12-21T15:38:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@ -2207,20 +2209,20 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/complexity",
|
||||
"version": "3.1.0",
|
||||
"version": "3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/complexity.git",
|
||||
"reference": "68cfb347a44871f01e33ab0ef8215966432f6957"
|
||||
"reference": "68ff824baeae169ec9f2137158ee529584553799"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957",
|
||||
"reference": "68cfb347a44871f01e33ab0ef8215966432f6957",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799",
|
||||
"reference": "68ff824baeae169ec9f2137158ee529584553799",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nikic/php-parser": "^4.10",
|
||||
"nikic/php-parser": "^4.18 || ^5.0",
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
@ -2229,7 +2231,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.1-dev"
|
||||
"dev-main": "3.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -2253,7 +2255,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/complexity/issues",
|
||||
"security": "https://github.com/sebastianbergmann/complexity/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0"
|
||||
"source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2261,20 +2263,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-09-28T11:50:59+00:00"
|
||||
"time": "2023-12-21T08:37:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
"version": "5.0.3",
|
||||
"version": "5.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b"
|
||||
"reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
|
||||
"reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/fbf413a49e54f6b9b17e12d900ac7f6101591b7f",
|
||||
"reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2287,7 +2289,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "5.0-dev"
|
||||
"dev-main": "5.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -2320,7 +2322,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||
"security": "https://github.com/sebastianbergmann/diff/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/5.0.3"
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/5.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2328,7 +2330,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-05-01T07:48:21+00:00"
|
||||
"time": "2023-12-22T10:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/environment",
|
||||
@ -2536,20 +2538,20 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/lines-of-code",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
|
||||
"reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d"
|
||||
"reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d",
|
||||
"reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0",
|
||||
"reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nikic/php-parser": "^4.10",
|
||||
"nikic/php-parser": "^4.18 || ^5.0",
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
@ -2582,7 +2584,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
|
||||
"security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1"
|
||||
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2590,7 +2592,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-08-31T09:25:50+00:00"
|
||||
"time": "2023-12-21T08:38:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/object-enumerator",
|
||||
@ -2878,16 +2880,16 @@
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
"version": "1.2.1",
|
||||
"version": "1.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/theseer/tokenizer.git",
|
||||
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
|
||||
"reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
|
||||
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
|
||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
|
||||
"reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2916,7 +2918,7 @@
|
||||
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
|
||||
"support": {
|
||||
"issues": "https://github.com/theseer/tokenizer/issues",
|
||||
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
|
||||
"source": "https://github.com/theseer/tokenizer/tree/1.2.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2924,7 +2926,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-07-28T10:34:58+00:00"
|
||||
"time": "2023-11-20T00:12:19+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
@ -45,4 +45,6 @@ final class BootstrapOptions{
|
||||
public const PLUGINS = "plugins";
|
||||
/** Path to store and load server data */
|
||||
public const DATA = "data";
|
||||
/** Shows basic server version information and exits */
|
||||
public const VERSION = "version";
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine {
|
||||
|
||||
use Composer\InstalledVersions;
|
||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||
use pocketmine\thread\ThreadManager;
|
||||
use pocketmine\thread\ThreadSafeClassLoader;
|
||||
use pocketmine\utils\Filesystem;
|
||||
@ -40,14 +41,17 @@ namespace pocketmine {
|
||||
use function extension_loaded;
|
||||
use function function_exists;
|
||||
use function getcwd;
|
||||
use function getopt;
|
||||
use function is_dir;
|
||||
use function mkdir;
|
||||
use function phpversion;
|
||||
use function preg_match;
|
||||
use function preg_quote;
|
||||
use function printf;
|
||||
use function realpath;
|
||||
use function version_compare;
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const PHP_EOL;
|
||||
|
||||
require_once __DIR__ . '/VersionInfo.php';
|
||||
|
||||
@ -166,7 +170,7 @@ namespace pocketmine {
|
||||
* @return void
|
||||
*/
|
||||
function emit_performance_warnings(\Logger $logger){
|
||||
if(PHP_DEBUG !== 0){
|
||||
if(ZEND_DEBUG_BUILD){
|
||||
$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)){
|
||||
@ -273,6 +277,11 @@ JIT_WARNING
|
||||
|
||||
ErrorToExceptionHandler::set();
|
||||
|
||||
if(count(getopt("", [BootstrapOptions::VERSION])) > 0){
|
||||
printf("%s %s (git hash %s) for Minecraft: Bedrock Edition %s\n", VersionInfo::NAME, VersionInfo::VERSION()->getFullVersion(true), VersionInfo::GIT_HASH(), ProtocolInfo::MINECRAFT_VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
|
||||
$dataPath = getopt_string(BootstrapOptions::DATA) ?? $cwd;
|
||||
$pluginPath = getopt_string(BootstrapOptions::PLUGINS) ?? $cwd . DIRECTORY_SEPARATOR . "plugins";
|
||||
|
@ -523,7 +523,7 @@ class Server{
|
||||
return $this->playerDataProvider->loadData($name);
|
||||
}catch(PlayerDataLoadException $e){
|
||||
$this->logger->debug("Failed to load player data for $name: " . $e->getMessage());
|
||||
$this->logger->error($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_playerCorrupted($name)));
|
||||
$this->logger->error($this->language->translate(KnownTranslationFactory::pocketmine_data_playerCorrupted($name)));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@ -542,7 +542,7 @@ class Server{
|
||||
try{
|
||||
$this->playerDataProvider->saveData($name, $ev->getSaveData());
|
||||
}catch(PlayerDataSaveException $e){
|
||||
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
|
||||
$this->logger->critical($this->language->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
});
|
||||
@ -854,7 +854,7 @@ class Server{
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::language_selected($this->getLanguage()->getName(), $this->getLanguage()->getLang())));
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::language_selected($this->language->getName(), $this->language->getLang())));
|
||||
|
||||
if(VersionInfo::IS_DEVELOPMENT_BUILD){
|
||||
if(!$this->configGroup->getPropertyBool(Yml::SETTINGS_ENABLE_DEV_BUILDS, false)){
|
||||
@ -877,7 +877,7 @@ class Server{
|
||||
|
||||
$this->memoryManager = new MemoryManager($this);
|
||||
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_start(TextFormat::AQUA . $this->getVersion() . TextFormat::RESET)));
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_start(TextFormat::AQUA . $this->getVersion() . TextFormat::RESET)));
|
||||
|
||||
if(($poolSize = $this->configGroup->getPropertyString(Yml::SETTINGS_ASYNC_WORKERS, "auto")) === "auto"){
|
||||
$poolSize = 2;
|
||||
@ -937,11 +937,11 @@ class Server{
|
||||
|
||||
$this->onlineMode = $this->configGroup->getConfigBool(ServerProperties::XBOX_AUTH, true);
|
||||
if($this->onlineMode){
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_auth_enabled()));
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_auth_enabled()));
|
||||
}else{
|
||||
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_auth_disabled()));
|
||||
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_authWarning()));
|
||||
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_authProperty_disabled()));
|
||||
$this->logger->warning($this->language->translate(KnownTranslationFactory::pocketmine_server_auth_disabled()));
|
||||
$this->logger->warning($this->language->translate(KnownTranslationFactory::pocketmine_server_authWarning()));
|
||||
$this->logger->warning($this->language->translate(KnownTranslationFactory::pocketmine_server_authProperty_disabled()));
|
||||
}
|
||||
|
||||
if($this->configGroup->getConfigBool(ServerProperties::HARDCORE, false) && $this->getDifficulty() < World::DIFFICULTY_HARD){
|
||||
@ -952,17 +952,17 @@ class Server{
|
||||
|
||||
$this->serverID = Utils::getMachineUniqueId($this->getIp() . $this->getPort());
|
||||
|
||||
$this->getLogger()->debug("Server unique id: " . $this->getServerUniqueId());
|
||||
$this->getLogger()->debug("Machine unique id: " . Utils::getMachineUniqueId());
|
||||
$this->logger->debug("Server unique id: " . $this->getServerUniqueId());
|
||||
$this->logger->debug("Machine unique id: " . Utils::getMachineUniqueId());
|
||||
|
||||
$this->network = new Network($this->logger);
|
||||
$this->network->setName($this->getMotd());
|
||||
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_info(
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_info(
|
||||
$this->getName(),
|
||||
(VersionInfo::IS_DEVELOPMENT_BUILD ? TextFormat::YELLOW : "") . $this->getPocketMineVersion() . TextFormat::RESET
|
||||
)));
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_license($this->getName())));
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_license($this->getName())));
|
||||
|
||||
TimingsHandler::setEnabled($this->configGroup->getPropertyBool(Yml::SETTINGS_ENABLE_PROFILING, false));
|
||||
$this->profilingTickRate = $this->configGroup->getPropertyInt(Yml::SETTINGS_PROFILE_REPORT_TRIGGER, self::TARGET_TICKS_PER_SECOND);
|
||||
@ -973,7 +973,7 @@ class Server{
|
||||
|
||||
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes"));
|
||||
|
||||
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
|
||||
$this->resourceManager = new ResourcePackManager(Path::join($this->dataPath, "resource_packs"), $this->logger);
|
||||
|
||||
$pluginGraylist = null;
|
||||
$graylistFile = Path::join($this->dataPath, "plugin_list.yml");
|
||||
@ -987,7 +987,7 @@ class Server{
|
||||
$this->forceShutdownExit();
|
||||
return;
|
||||
}
|
||||
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool(Yml::PLUGINS_LEGACY_DATA_DIR, true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
|
||||
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool(Yml::PLUGINS_LEGACY_DATA_DIR, true) ? null : Path::join($this->dataPath, "plugin_data"), $pluginGraylist);
|
||||
$this->pluginManager->registerInterface(new PharPluginLoader($this->autoloader));
|
||||
$this->pluginManager->registerInterface(new ScriptPluginLoader());
|
||||
|
||||
@ -1049,9 +1049,9 @@ class Server{
|
||||
|
||||
$this->configGroup->save();
|
||||
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_defaultGameMode($this->getGamemode()->getTranslatableName())));
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_donate(TextFormat::AQUA . "https://patreon.com/pocketminemp" . TextFormat::RESET)));
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_startFinished(strval(round(microtime(true) - $this->startTime, 3)))));
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_defaultGameMode($this->getGamemode()->getTranslatableName())));
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_donate(TextFormat::AQUA . "https://patreon.com/pocketminemp" . TextFormat::RESET)));
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_startFinished(strval(round(microtime(true) - $this->startTime, 3)))));
|
||||
|
||||
$forwarder = new BroadcastLoggerForwarder($this, $this->logger, $this->language);
|
||||
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_ADMINISTRATIVE, $forwarder);
|
||||
@ -1139,13 +1139,13 @@ class Server{
|
||||
if($this->worldManager->getDefaultWorld() === null){
|
||||
$default = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_NAME, "world");
|
||||
if(trim($default) == ""){
|
||||
$this->getLogger()->warning("level-name cannot be null, using default");
|
||||
$this->logger->warning("level-name cannot be null, using default");
|
||||
$default = "world";
|
||||
$this->configGroup->setConfigString(ServerProperties::DEFAULT_WORLD_NAME, "world");
|
||||
}
|
||||
if(!$this->worldManager->loadWorld($default, true)){
|
||||
if($this->worldManager->isWorldGenerated($default)){
|
||||
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -1154,7 +1154,7 @@ class Server{
|
||||
$generatorClass = $getGenerator($generatorName, $generatorOptions, $default);
|
||||
|
||||
if($generatorClass === null){
|
||||
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
|
||||
return false;
|
||||
}
|
||||
$creationOptions = WorldCreationOptions::create()
|
||||
@ -1200,7 +1200,7 @@ class Server{
|
||||
return false;
|
||||
}
|
||||
if($rakLibRegistered){
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_networkStart($prettyIp, (string) $port)));
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStart($prettyIp, (string) $port)));
|
||||
}
|
||||
if($useQuery){
|
||||
if(!$rakLibRegistered){
|
||||
@ -1208,7 +1208,7 @@ class Server{
|
||||
//if it's not registered we need to make sure Query still works
|
||||
$this->network->registerInterface(new DedicatedQueryNetworkInterface($ip, $port, $ipV6, new \PrefixedLogger($this->logger, "Dedicated Query Interface")));
|
||||
}
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_query_running($prettyIp, (string) $port)));
|
||||
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_query_running($prettyIp, (string) $port)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1356,11 +1356,19 @@ class Server{
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a list of packets in a batch to a list of players
|
||||
* @internal
|
||||
* Promises to compress the given batch buffer using the selected compressor, optionally on a separate thread.
|
||||
*
|
||||
* If the buffer is smaller than the batch-threshold (usually 256), the buffer will be compressed at level 0 if supported
|
||||
* by the compressor. This means that the payload will be wrapped with the appropriate header and footer, but not
|
||||
* actually compressed.
|
||||
*
|
||||
* If the buffer is larger than the async-compression-threshold (usually 10,000), the buffer may be compressed in
|
||||
* a separate thread (if available).
|
||||
*
|
||||
* @param bool|null $sync Compression on the main thread (true) or workers (false). Default is automatic (null).
|
||||
*/
|
||||
public function prepareBatch(string $buffer, Compressor $compressor, ?bool $sync = null, ?TimingsHandler $timings = null) : CompressBatchPromise{
|
||||
public function prepareBatch(string $buffer, Compressor $compressor, ?bool $sync = null, ?TimingsHandler $timings = null) : CompressBatchPromise|string{
|
||||
$timings ??= Timings::$playerNetworkSendCompress;
|
||||
try{
|
||||
$timings->startTiming();
|
||||
@ -1370,15 +1378,14 @@ class Server{
|
||||
$sync = !$this->networkCompressionAsync || $threshold === null || strlen($buffer) < $threshold;
|
||||
}
|
||||
|
||||
$promise = new CompressBatchPromise();
|
||||
if(!$sync && strlen($buffer) >= $this->networkCompressionAsyncThreshold){
|
||||
$promise = new CompressBatchPromise();
|
||||
$task = new CompressBatchTask($buffer, $promise, $compressor);
|
||||
$this->asyncPool->submitTask($task);
|
||||
}else{
|
||||
$promise->resolve($compressor->compress($buffer));
|
||||
return $promise;
|
||||
}
|
||||
|
||||
return $promise;
|
||||
return $compressor->compress($buffer);
|
||||
}finally{
|
||||
$timings->stopTiming();
|
||||
}
|
||||
@ -1455,7 +1462,7 @@ class Server{
|
||||
$this->shutdown();
|
||||
|
||||
if(isset($this->pluginManager)){
|
||||
$this->getLogger()->debug("Disabling all plugins");
|
||||
$this->logger->debug("Disabling all plugins");
|
||||
$this->pluginManager->disablePlugins();
|
||||
}
|
||||
|
||||
@ -1464,34 +1471,34 @@ class Server{
|
||||
}
|
||||
|
||||
if(isset($this->worldManager)){
|
||||
$this->getLogger()->debug("Unloading all worlds");
|
||||
$this->logger->debug("Unloading all worlds");
|
||||
foreach($this->worldManager->getWorlds() as $world){
|
||||
$this->worldManager->unloadWorld($world, true);
|
||||
}
|
||||
}
|
||||
|
||||
$this->getLogger()->debug("Removing event handlers");
|
||||
$this->logger->debug("Removing event handlers");
|
||||
HandlerListManager::global()->unregisterAll();
|
||||
|
||||
if(isset($this->asyncPool)){
|
||||
$this->getLogger()->debug("Shutting down async task worker pool");
|
||||
$this->logger->debug("Shutting down async task worker pool");
|
||||
$this->asyncPool->shutdown();
|
||||
}
|
||||
|
||||
if(isset($this->configGroup)){
|
||||
$this->getLogger()->debug("Saving properties");
|
||||
$this->logger->debug("Saving properties");
|
||||
$this->configGroup->save();
|
||||
}
|
||||
|
||||
if($this->console !== null){
|
||||
$this->getLogger()->debug("Closing console");
|
||||
$this->logger->debug("Closing console");
|
||||
$this->console->quit();
|
||||
}
|
||||
|
||||
if(isset($this->network)){
|
||||
$this->getLogger()->debug("Stopping network interfaces");
|
||||
$this->logger->debug("Stopping network interfaces");
|
||||
foreach($this->network->getInterfaces() as $interface){
|
||||
$this->getLogger()->debug("Stopping network interface " . get_class($interface));
|
||||
$this->logger->debug("Stopping network interface " . get_class($interface));
|
||||
$this->network->unregisterInterface($interface);
|
||||
}
|
||||
}
|
||||
@ -1559,7 +1566,7 @@ class Server{
|
||||
}
|
||||
|
||||
private function writeCrashDumpFile(CrashDump $dump) : string{
|
||||
$crashFolder = Path::join($this->getDataPath(), "crashdumps");
|
||||
$crashFolder = Path::join($this->dataPath, "crashdumps");
|
||||
if(!is_dir($crashFolder)){
|
||||
mkdir($crashFolder);
|
||||
}
|
||||
@ -1590,17 +1597,17 @@ class Server{
|
||||
ini_set("error_reporting", '0');
|
||||
ini_set("memory_limit", '-1'); //Fix error dump not dumped on memory problems
|
||||
try{
|
||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_create()));
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_crash_create()));
|
||||
$dump = new CrashDump($this, $this->pluginManager ?? null);
|
||||
|
||||
$crashDumpPath = $this->writeCrashDumpFile($dump);
|
||||
|
||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_submit($crashDumpPath)));
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_crash_submit($crashDumpPath)));
|
||||
|
||||
if($this->configGroup->getPropertyBool(Yml::AUTO_REPORT_ENABLED, true)){
|
||||
$report = true;
|
||||
|
||||
$stamp = Path::join($this->getDataPath(), "crashdumps", ".last_crash");
|
||||
$stamp = Path::join($this->dataPath, "crashdumps", ".last_crash");
|
||||
$crashInterval = 120; //2 minutes
|
||||
if(($lastReportTime = @filemtime($stamp)) !== false && $lastReportTime + $crashInterval >= time()){
|
||||
$report = false;
|
||||
@ -1631,7 +1638,7 @@ class Server{
|
||||
if(isset($data->crashId) && is_int($data->crashId) && isset($data->crashUrl) && is_string($data->crashUrl)){
|
||||
$reportId = $data->crashId;
|
||||
$reportUrl = $data->crashUrl;
|
||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_archive($reportUrl, (string) $reportId)));
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_crash_archive($reportUrl, (string) $reportId)));
|
||||
}elseif(isset($data->error) && is_string($data->error)){
|
||||
$this->logger->emergency("Automatic crash report submission failed: $data->error");
|
||||
}else{
|
||||
@ -1645,7 +1652,7 @@ class Server{
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->logException($e);
|
||||
try{
|
||||
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_error($e->getMessage())));
|
||||
$this->logger->critical($this->language->translate(KnownTranslationFactory::pocketmine_crash_error($e->getMessage())));
|
||||
}catch(\Throwable $e){}
|
||||
}
|
||||
|
||||
@ -1763,7 +1770,7 @@ class Server{
|
||||
|
||||
echo "\x1b]0;" . $this->getName() . " " .
|
||||
$this->getPocketMineVersion() .
|
||||
" | Online $online/" . $this->getMaxPlayers() .
|
||||
" | Online $online/" . $this->maxPlayers .
|
||||
($connecting > 0 ? " (+$connecting connecting)" : "") .
|
||||
" | Memory " . $usage .
|
||||
" | U " . round($bandwidthStats->getSend()->getAverageBytes() / 1024, 2) .
|
||||
@ -1828,10 +1835,10 @@ class Server{
|
||||
}
|
||||
|
||||
if(($this->tickCounter % self::TICKS_PER_TPS_OVERLOAD_WARNING) === 0 && $this->getTicksPerSecondAverage() < self::TPS_OVERLOAD_WARNING_THRESHOLD){
|
||||
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
|
||||
$this->logger->warning($this->language->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
|
||||
}
|
||||
|
||||
$this->getMemoryManager()->check();
|
||||
$this->memoryManager->check();
|
||||
|
||||
if($this->console !== null){
|
||||
Timings::$serverCommand->startTiming();
|
||||
|
@ -24,7 +24,9 @@ declare(strict_types=1);
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\snooze\SleeperHandler;
|
||||
use pocketmine\snooze\SleeperHandlerEntry;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use pocketmine\utils\Utils;
|
||||
use function hrtime;
|
||||
|
||||
/**
|
||||
@ -35,12 +37,29 @@ final class TimeTrackingSleeperHandler extends SleeperHandler{
|
||||
|
||||
private int $notificationProcessingTimeNs = 0;
|
||||
|
||||
/**
|
||||
* @var TimingsHandler[]
|
||||
* @phpstan-var array<string, TimingsHandler>
|
||||
*/
|
||||
private static array $handlerTimings = [];
|
||||
|
||||
public function __construct(
|
||||
private TimingsHandler $timings
|
||||
){
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function addNotifier(\Closure $handler) : SleeperHandlerEntry{
|
||||
$name = Utils::getNiceClosureName($handler);
|
||||
$timings = self::$handlerTimings[$name] ??= new TimingsHandler("Snooze Handler: " . $name, $this->timings);
|
||||
|
||||
return parent::addNotifier(function() use ($timings, $handler) : void{
|
||||
$timings->startTiming();
|
||||
$handler();
|
||||
$timings->stopTiming();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time in nanoseconds spent processing notifications since the last reset.
|
||||
*/
|
||||
|
@ -31,7 +31,7 @@ use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "5.8.3";
|
||||
public const BASE_VERSION = "5.10.1";
|
||||
public const IS_DEVELOPMENT_BUILD = true;
|
||||
public const BUILD_CHANNEL = "stable";
|
||||
|
||||
|
@ -173,7 +173,7 @@ class Bamboo extends Transparent{
|
||||
$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
|
||||
if($newHeight >= 4 && !$stemBlock->thick){ //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);
|
||||
|
@ -55,12 +55,12 @@ class Barrel extends Opaque{
|
||||
|
||||
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(abs($player->getPosition()->x - $this->position->x) < 2 && abs($player->getPosition()->z - $this->position->z) < 2){
|
||||
$y = $player->getEyePos()->y;
|
||||
|
||||
if($y - $this->position->getY() > 2){
|
||||
if($y - $this->position->y > 2){
|
||||
$this->facing = Facing::UP;
|
||||
}elseif($this->position->getY() - $y > 0){
|
||||
}elseif($this->position->y - $y > 0){
|
||||
$this->facing = Facing::DOWN;
|
||||
}else{
|
||||
$this->facing = Facing::opposite($player->getHorizontalFacing());
|
||||
|
@ -34,7 +34,6 @@ 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;
|
||||
|
||||
@ -89,11 +88,12 @@ abstract class BaseBanner extends Transparent{
|
||||
* @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");
|
||||
foreach($patterns as $pattern){
|
||||
if(!$pattern instanceof BannerPatternLayer){
|
||||
throw new \TypeError("Array must only contain " . BannerPatternLayer::class . " objects");
|
||||
}
|
||||
}
|
||||
$this->patterns = $checked;
|
||||
$this->patterns = $patterns;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -65,8 +65,8 @@ abstract class BaseBigDripleaf extends Transparent{
|
||||
$this->facing = Facing::opposite($player->getHorizontalFacing());
|
||||
}
|
||||
if($block instanceof BaseBigDripleaf){
|
||||
$this->facing = $block->getFacing();
|
||||
$tx->addBlock($block->getPosition(), VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($this->facing));
|
||||
$this->facing = $block->facing;
|
||||
$tx->addBlock($block->position, VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($this->facing));
|
||||
}
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
@ -98,7 +98,7 @@ abstract class BaseBigDripleaf extends Transparent{
|
||||
if($head === null){
|
||||
return false;
|
||||
}
|
||||
$pos = $head->getPosition();
|
||||
$pos = $head->position;
|
||||
$up = $pos->up();
|
||||
$world = $pos->getWorld();
|
||||
if(
|
||||
@ -110,8 +110,8 @@ abstract class BaseBigDripleaf extends Transparent{
|
||||
|
||||
$tx = new BlockTransaction($world);
|
||||
|
||||
$tx->addBlock($pos, VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($head->getFacing()));
|
||||
$tx->addBlock($up, VanillaBlocks::BIG_DRIPLEAF_HEAD()->setFacing($head->getFacing()));
|
||||
$tx->addBlock($pos, VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($head->facing));
|
||||
$tx->addBlock($up, VanillaBlocks::BIG_DRIPLEAF_HEAD()->setFacing($head->facing));
|
||||
|
||||
$ev = new StructureGrowEvent($head, $tx, $player);
|
||||
$ev->call();
|
||||
|
@ -145,7 +145,7 @@ class Bed extends Transparent{
|
||||
|
||||
$b = ($this->isHeadPart() ? $this : $other);
|
||||
|
||||
if($b->isOccupied()){
|
||||
if($b->occupied){
|
||||
$player->sendMessage(KnownTranslationFactory::tile_bed_occupied()->prefix(TextFormat::GRAY));
|
||||
|
||||
return true;
|
||||
|
@ -402,7 +402,7 @@ class Block{
|
||||
}
|
||||
|
||||
/**
|
||||
* AKA: Block->isPlaceable
|
||||
* Returns whether this block can be placed when obtained as an item.
|
||||
*/
|
||||
public function canBePlaced() : bool{
|
||||
return true;
|
||||
@ -572,16 +572,28 @@ class Block{
|
||||
return $this->getLightFilter() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block allows any light to pass through it.
|
||||
*/
|
||||
public function isTransparent() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated TL;DR: Don't use this function. Its results are confusing and inconsistent.
|
||||
*
|
||||
* No one is sure what the meaning of this property actually is. It's borrowed from Minecraft Java Edition, and is
|
||||
* used by various blocks for support checks.
|
||||
*
|
||||
* Things like signs and banners are considered "solid" despite having no collision box, and things like skulls and
|
||||
* flower pots are considered non-solid despite obviously being "solid" in the conventional, real-world sense.
|
||||
*/
|
||||
public function isSolid() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* AKA: Block->isFlowable
|
||||
* Returns whether this block can be destroyed by liquid flowing into its cell.
|
||||
*/
|
||||
public function canBeFlowedInto() : bool{
|
||||
return false;
|
||||
|
@ -97,7 +97,7 @@ class ChiseledBookshelf extends Opaque{
|
||||
return false;
|
||||
}
|
||||
|
||||
$x = Facing::axis($face) === Axis::X ? $clickVector->getZ() : $clickVector->getX();
|
||||
$x = Facing::axis($face) === Axis::X ? $clickVector->z : $clickVector->x;
|
||||
$slot = ChiseledBookshelfSlot::fromBlockFaceCoordinates(
|
||||
Facing::isPositive(Facing::rotateY($face, true)) ? 1 - $x : $x,
|
||||
$clickVector->y
|
||||
|
@ -54,7 +54,7 @@ final class ChorusFlower extends Flowable{
|
||||
}
|
||||
|
||||
private function canBeSupportedAt(Block $block) : bool{
|
||||
$position = $block->getPosition();
|
||||
$position = $block->position;
|
||||
$world = $position->getWorld();
|
||||
$down = $world->getBlock($position->down());
|
||||
|
||||
@ -152,7 +152,7 @@ final class ChorusFlower extends Flowable{
|
||||
if($tx === null){
|
||||
$tx = new BlockTransaction($this->position->getWorld());
|
||||
}
|
||||
$tx->addBlock($this->position->getSide($facing), (clone $this)->setAge(min(self::MAX_AGE, $this->getAge() + $ageChange)));
|
||||
$tx->addBlock($this->position->getSide($facing), (clone $this)->setAge(min(self::MAX_AGE, $this->age + $ageChange)));
|
||||
|
||||
return $tx;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ final class ChorusPlant extends Flowable{
|
||||
}
|
||||
|
||||
private function canBeSupportedAt(Block $block) : bool{
|
||||
$position = $block->getPosition();
|
||||
$position = $block->position;
|
||||
$world = $position->getWorld();
|
||||
|
||||
$down = $world->getBlock($position->down());
|
||||
|
@ -29,6 +29,7 @@ use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\event\block\StructureGrowEvent;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Axis;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
@ -106,4 +107,14 @@ final class DoublePitcherCrop extends DoublePlant{
|
||||
$this->grow(null);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
$this->age >= self::MAX_AGE ? VanillaBlocks::PITCHER_PLANT()->asItem() : VanillaItems::PITCHER_POD()
|
||||
];
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaItems::PITCHER_POD();
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ class Farmland extends Transparent{
|
||||
$ev = new EntityTrampleFarmlandEvent($entity, $this);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getPosition()->getWorld()->setBlock($this->getPosition(), VanillaBlocks::DIRT());
|
||||
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::DIRT());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -140,7 +140,7 @@ class Fire extends BaseFire{
|
||||
$block->onIncinerate();
|
||||
|
||||
$world = $this->position->getWorld();
|
||||
if($world->getBlock($block->getPosition())->isSameState($block)){
|
||||
if($world->getBlock($block->position)->isSameState($block)){
|
||||
$spreadedFire = false;
|
||||
if(mt_rand(0, $this->age + 9) < 5){ //TODO: check rain
|
||||
$fire = clone $this;
|
||||
|
@ -58,7 +58,7 @@ final class FloorCoralFan extends BaseCoral{
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($player !== null){
|
||||
$playerBlockPos = $player->getPosition()->floor();
|
||||
$directionVector = $blockReplace->getPosition()->subtractVector($playerBlockPos)->normalize();
|
||||
$directionVector = $blockReplace->position->subtractVector($playerBlockPos)->normalize();
|
||||
$angle = rad2deg(atan2($directionVector->getZ(), $directionVector->getX()));
|
||||
|
||||
if($angle <= 45 || 315 <= $angle || (135 <= $angle && $angle <= 225)){
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\tile\Furnace as TileFurnace;
|
||||
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
|
||||
use pocketmine\block\utils\LightableTrait;
|
||||
use pocketmine\crafting\FurnaceType;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\item\Item;
|
||||
@ -34,11 +35,10 @@ use function mt_rand;
|
||||
|
||||
class Furnace extends Opaque{
|
||||
use FacesOppositePlacingPlayerTrait;
|
||||
use LightableTrait;
|
||||
|
||||
protected FurnaceType $furnaceType;
|
||||
|
||||
protected bool $lit = false;
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo, FurnaceType $furnaceType){
|
||||
$this->furnaceType = $furnaceType;
|
||||
parent::__construct($idInfo, $name, $typeInfo);
|
||||
@ -57,18 +57,6 @@ class Furnace extends Opaque{
|
||||
return $this->lit ? 13 : 0;
|
||||
}
|
||||
|
||||
public function isLit() : bool{
|
||||
return $this->lit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setLit(bool $lit = true) : self{
|
||||
$this->lit = $lit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($player instanceof Player){
|
||||
$furnace = $this->position->getWorld()->getTile($this->position);
|
||||
|
@ -61,7 +61,7 @@ class Jukebox extends Opaque{
|
||||
|
||||
public function ejectRecord() : void{
|
||||
if($this->record !== null){
|
||||
$this->getPosition()->getWorld()->dropItem($this->getPosition()->add(0.5, 1, 0.5), $this->record);
|
||||
$this->position->getWorld()->dropItem($this->position->add(0.5, 1, 0.5), $this->record);
|
||||
$this->record = null;
|
||||
$this->stopSound();
|
||||
}
|
||||
@ -76,12 +76,12 @@ class Jukebox extends Opaque{
|
||||
|
||||
public function startSound() : void{
|
||||
if($this->record !== null){
|
||||
$this->getPosition()->getWorld()->addSound($this->getPosition(), new RecordSound($this->record->getRecordType()));
|
||||
$this->position->getWorld()->addSound($this->position, new RecordSound($this->record->getRecordType()));
|
||||
}
|
||||
}
|
||||
|
||||
public function stopSound() : void{
|
||||
$this->getPosition()->getWorld()->addSound($this->getPosition(), new RecordStopSound());
|
||||
$this->position->getWorld()->addSound($this->position, new RecordStopSound());
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
|
@ -108,8 +108,8 @@ class NetherVines extends Flowable{
|
||||
|
||||
private function grow(?Player $player, int $growthAmount = 1) : bool{
|
||||
$top = $this->seekToTip();
|
||||
$age = $top->getAge();
|
||||
$pos = $top->getPosition();
|
||||
$age = $top->age;
|
||||
$pos = $top->position;
|
||||
$world = $pos->getWorld();
|
||||
$changedBlocks = 0;
|
||||
|
||||
|
@ -70,13 +70,13 @@ class PinkPetals extends Flowable{
|
||||
}
|
||||
|
||||
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
|
||||
return ($blockReplace instanceof PinkPetals && $blockReplace->getCount() < self::MAX_COUNT) || $this->supportedWhenPlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
|
||||
return ($blockReplace instanceof PinkPetals && $blockReplace->count < self::MAX_COUNT) || $this->supportedWhenPlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($blockReplace instanceof PinkPetals && $blockReplace->getCount() < self::MAX_COUNT){
|
||||
$this->count = $blockReplace->getCount() + 1;
|
||||
$this->facing = $blockReplace->getFacing();
|
||||
if($blockReplace instanceof PinkPetals && $blockReplace->count < self::MAX_COUNT){
|
||||
$this->count = $blockReplace->count + 1;
|
||||
$this->facing = $blockReplace->facing;
|
||||
}elseif($player !== null){
|
||||
$this->facing = Facing::opposite($player->getHorizontalFacing());
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\block\utils\StaticSupportTrait;
|
||||
use pocketmine\event\block\StructureGrowEvent;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Axis;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
@ -101,4 +102,8 @@ final class PitcherCrop extends Flowable{
|
||||
$this->grow(null);
|
||||
}
|
||||
}
|
||||
|
||||
public function asItem() : Item{
|
||||
return VanillaItems::PITCHER_POD();
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class RedMushroom extends Flowable{
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
$position = $this->getPosition();
|
||||
$position = $this->position;
|
||||
$lightLevel = $position->getWorld()->getFullLightAt($position->x, $position->y, $position->z);
|
||||
$downId = $down->getTypeId();
|
||||
//TODO: nylium support
|
||||
|
@ -24,7 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\FortuneDropHelper;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\block\utils\LightableTrait;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Vector3;
|
||||
@ -32,23 +32,7 @@ use pocketmine\player\Player;
|
||||
use function mt_rand;
|
||||
|
||||
class RedstoneOre extends Opaque{
|
||||
protected bool $lit = false;
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->bool($this->lit);
|
||||
}
|
||||
|
||||
public function isLit() : bool{
|
||||
return $this->lit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setLit(bool $lit = true) : self{
|
||||
$this->lit = $lit;
|
||||
return $this;
|
||||
}
|
||||
use LightableTrait;
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return $this->lit ? 9 : 0;
|
||||
|
@ -23,28 +23,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\LightableTrait;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
|
||||
class RedstoneTorch extends Torch{
|
||||
protected bool $lit = true;
|
||||
use LightableTrait;
|
||||
|
||||
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
|
||||
$this->lit = true;
|
||||
parent::__construct($idInfo, $name, $typeInfo);
|
||||
}
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
parent::describeBlockOnlyState($w);
|
||||
$w->bool($this->lit);
|
||||
}
|
||||
|
||||
public function isLit() : bool{
|
||||
return $this->lit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setLit(bool $lit = true) : self{
|
||||
$this->lit = $lit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return $this->lit ? 7 : 0;
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class SmallDripleaf extends Transparent{
|
||||
$this->facing = Facing::opposite($player->getHorizontalFacing());
|
||||
}
|
||||
|
||||
$tx->addBlock($block->getPosition(), VanillaBlocks::SMALL_DRIPLEAF()
|
||||
$tx->addBlock($block->position, VanillaBlocks::SMALL_DRIPLEAF()
|
||||
->setFacing($this->facing)
|
||||
->setTop(true)
|
||||
);
|
||||
@ -117,7 +117,7 @@ class SmallDripleaf extends Transparent{
|
||||
$height = mt_rand(2, 5);
|
||||
$grown = 0;
|
||||
for($i = 0; $i < $height; $i++){
|
||||
$pos = $bottomBlock->getSide(Facing::UP, $i)->getPosition();
|
||||
$pos = $bottomBlock->getSide(Facing::UP, $i)->position;
|
||||
if(!$this->canGrowTo($pos)){
|
||||
break;
|
||||
}
|
||||
|
@ -106,8 +106,8 @@ class Stair extends Transparent{
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
if(
|
||||
$facing === Facing::UP && $this->isUpsideDown() ||
|
||||
$facing === Facing::DOWN && !$this->isUpsideDown() ||
|
||||
$facing === Facing::UP && $this->upsideDown ||
|
||||
$facing === Facing::DOWN && !$this->upsideDown ||
|
||||
($facing === $this->facing && $this->shape !== StairShape::OUTER_LEFT && $this->shape !== StairShape::OUTER_RIGHT) ||
|
||||
($facing === Facing::rotate($this->facing, Axis::Y, false) && $this->shape === StairShape::INNER_LEFT) ||
|
||||
($facing === Facing::rotate($this->facing, Axis::Y, true) && $this->shape === StairShape::INNER_RIGHT)
|
||||
|
@ -47,20 +47,20 @@ trait AnimatedBlockInventoryTrait{
|
||||
public function onOpen(Player $who) : void{
|
||||
parent::onOpen($who);
|
||||
|
||||
if($this->getHolder()->isValid() && $this->getViewerCount() === 1){
|
||||
if($this->holder->isValid() && $this->getViewerCount() === 1){
|
||||
//TODO: this crap really shouldn't be managed by the inventory
|
||||
$this->animateBlock(true);
|
||||
$this->getHolder()->getWorld()->addSound($this->getHolder()->add(0.5, 0.5, 0.5), $this->getOpenSound());
|
||||
$this->holder->getWorld()->addSound($this->holder->add(0.5, 0.5, 0.5), $this->getOpenSound());
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected function animateBlock(bool $isOpen) : void;
|
||||
|
||||
public function onClose(Player $who) : void{
|
||||
if($this->getHolder()->isValid() && $this->getViewerCount() === 1){
|
||||
if($this->holder->isValid() && $this->getViewerCount() === 1){
|
||||
//TODO: this crap really shouldn't be managed by the inventory
|
||||
$this->animateBlock(false);
|
||||
$this->getHolder()->getWorld()->addSound($this->getHolder()->add(0.5, 0.5, 0.5), $this->getCloseSound());
|
||||
$this->holder->getWorld()->addSound($this->holder->add(0.5, 0.5, 0.5), $this->getCloseSound());
|
||||
}
|
||||
parent::onClose($who);
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ class Chest extends Spawnable implements Container, Nameable{
|
||||
if($pair->doubleInventory !== null){
|
||||
$this->doubleInventory = $pair->doubleInventory;
|
||||
}else{
|
||||
if(($pair->getPosition()->x + ($pair->getPosition()->z << 15)) > ($this->position->x + ($this->position->z << 15))){ //Order them correctly
|
||||
if(($pair->position->x + ($pair->position->z << 15)) > ($this->position->x + ($this->position->z << 15))){ //Order them correctly
|
||||
$this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($pair->inventory, $this->inventory);
|
||||
}else{
|
||||
$this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($this->inventory, $pair->inventory);
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\FloatTag;
|
||||
use pocketmine\network\mcpe\convert\TypeConverter;
|
||||
use pocketmine\world\World;
|
||||
|
||||
@ -52,13 +53,17 @@ class ItemFrame extends Spawnable{
|
||||
if(($itemTag = $nbt->getCompoundTag(self::TAG_ITEM)) !== null){
|
||||
$this->item = Item::nbtDeserialize($itemTag);
|
||||
}
|
||||
$this->itemRotation = $nbt->getByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
|
||||
if($nbt->getTag(self::TAG_ITEM_ROTATION) instanceof FloatTag){
|
||||
$this->itemRotation = (int) ($nbt->getFloat(self::TAG_ITEM_ROTATION, $this->itemRotation * 45) / 45);
|
||||
} else {
|
||||
$this->itemRotation = $nbt->getByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
|
||||
}
|
||||
$this->itemDropChance = $nbt->getFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
|
||||
$nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
|
||||
$nbt->setFloat(self::TAG_ITEM_ROTATION, $this->itemRotation * 45);
|
||||
if(!$this->item->isNull()){
|
||||
$nbt->setTag(self::TAG_ITEM, $this->item->nbtSerialize());
|
||||
}
|
||||
@ -98,7 +103,7 @@ class ItemFrame extends Spawnable{
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
|
||||
$nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
|
||||
$nbt->setFloat(self::TAG_ITEM_ROTATION, $this->itemRotation * 45);
|
||||
if(!$this->item->isNull()){
|
||||
$nbt->setTag(self::TAG_ITEM, TypeConverter::getInstance()->getItemTranslator()->toNetworkNbt($this->item));
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block\utils;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\entity\projectile\Projectile;
|
||||
use pocketmine\item\Durable;
|
||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||
@ -38,24 +37,12 @@ use pocketmine\world\sound\FireExtinguishSound;
|
||||
use pocketmine\world\sound\FlintSteelSound;
|
||||
|
||||
trait CandleTrait{
|
||||
private bool $lit = false;
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->bool($this->lit);
|
||||
}
|
||||
use LightableTrait;
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return $this->lit ? 3 : 0;
|
||||
}
|
||||
|
||||
public function isLit() : bool{ return $this->lit; }
|
||||
|
||||
/** @return $this */
|
||||
public function setLit(bool $lit) : self{
|
||||
$this->lit = $lit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @see Block::onInteract() */
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item->getTypeId() === ItemTypeIds::FIRE_CHARGE || $item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
|
||||
|
46
src/block/utils/LightableTrait.php
Normal file
46
src/block/utils/LightableTrait.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?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\utils;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
|
||||
trait LightableTrait{
|
||||
protected bool $lit = false;
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->bool($this->lit);
|
||||
}
|
||||
|
||||
public function isLit() : bool{
|
||||
return $this->lit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setLit(bool $lit = true) : self{
|
||||
$this->lit = $lit;
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -43,44 +43,48 @@ final class BannerPatternTypeIdMap{
|
||||
private array $enumToId = [];
|
||||
|
||||
public function __construct(){
|
||||
$this->register("bo", BannerPatternType::BORDER);
|
||||
$this->register("bri", BannerPatternType::BRICKS);
|
||||
$this->register("mc", BannerPatternType::CIRCLE);
|
||||
$this->register("cre", BannerPatternType::CREEPER);
|
||||
$this->register("cr", BannerPatternType::CROSS);
|
||||
$this->register("cbo", BannerPatternType::CURLY_BORDER);
|
||||
$this->register("lud", BannerPatternType::DIAGONAL_LEFT);
|
||||
$this->register("rd", BannerPatternType::DIAGONAL_RIGHT);
|
||||
$this->register("ld", BannerPatternType::DIAGONAL_UP_LEFT);
|
||||
$this->register("rud", BannerPatternType::DIAGONAL_UP_RIGHT);
|
||||
$this->register("flo", BannerPatternType::FLOWER);
|
||||
$this->register("gra", BannerPatternType::GRADIENT);
|
||||
$this->register("gru", BannerPatternType::GRADIENT_UP);
|
||||
$this->register("hh", BannerPatternType::HALF_HORIZONTAL);
|
||||
$this->register("hhb", BannerPatternType::HALF_HORIZONTAL_BOTTOM);
|
||||
$this->register("vh", BannerPatternType::HALF_VERTICAL);
|
||||
$this->register("vhr", BannerPatternType::HALF_VERTICAL_RIGHT);
|
||||
$this->register("moj", BannerPatternType::MOJANG);
|
||||
$this->register("mr", BannerPatternType::RHOMBUS);
|
||||
$this->register("sku", BannerPatternType::SKULL);
|
||||
$this->register("ss", BannerPatternType::SMALL_STRIPES);
|
||||
$this->register("bl", BannerPatternType::SQUARE_BOTTOM_LEFT);
|
||||
$this->register("br", BannerPatternType::SQUARE_BOTTOM_RIGHT);
|
||||
$this->register("tl", BannerPatternType::SQUARE_TOP_LEFT);
|
||||
$this->register("tr", BannerPatternType::SQUARE_TOP_RIGHT);
|
||||
$this->register("sc", BannerPatternType::STRAIGHT_CROSS);
|
||||
$this->register("bs", BannerPatternType::STRIPE_BOTTOM);
|
||||
$this->register("cs", BannerPatternType::STRIPE_CENTER);
|
||||
$this->register("dls", BannerPatternType::STRIPE_DOWNLEFT);
|
||||
$this->register("drs", BannerPatternType::STRIPE_DOWNRIGHT);
|
||||
$this->register("ls", BannerPatternType::STRIPE_LEFT);
|
||||
$this->register("ms", BannerPatternType::STRIPE_MIDDLE);
|
||||
$this->register("rs", BannerPatternType::STRIPE_RIGHT);
|
||||
$this->register("ts", BannerPatternType::STRIPE_TOP);
|
||||
$this->register("bt", BannerPatternType::TRIANGLE_BOTTOM);
|
||||
$this->register("tt", BannerPatternType::TRIANGLE_TOP);
|
||||
$this->register("bts", BannerPatternType::TRIANGLES_BOTTOM);
|
||||
$this->register("tts", BannerPatternType::TRIANGLES_TOP);
|
||||
foreach(BannerPatternType::cases() as $case){
|
||||
$this->register(match($case){
|
||||
BannerPatternType::BORDER => "bo",
|
||||
BannerPatternType::BRICKS => "bri",
|
||||
BannerPatternType::CIRCLE => "mc",
|
||||
BannerPatternType::CREEPER => "cre",
|
||||
BannerPatternType::CROSS => "cr",
|
||||
BannerPatternType::CURLY_BORDER => "cbo",
|
||||
BannerPatternType::DIAGONAL_LEFT => "lud",
|
||||
BannerPatternType::DIAGONAL_RIGHT => "rd",
|
||||
BannerPatternType::DIAGONAL_UP_LEFT => "ld",
|
||||
BannerPatternType::DIAGONAL_UP_RIGHT => "rud",
|
||||
BannerPatternType::FLOWER => "flo",
|
||||
BannerPatternType::GRADIENT => "gra",
|
||||
BannerPatternType::GRADIENT_UP => "gru",
|
||||
BannerPatternType::HALF_HORIZONTAL => "hh",
|
||||
BannerPatternType::HALF_HORIZONTAL_BOTTOM => "hhb",
|
||||
BannerPatternType::HALF_VERTICAL => "vh",
|
||||
BannerPatternType::HALF_VERTICAL_RIGHT => "vhr",
|
||||
BannerPatternType::MOJANG => "moj",
|
||||
BannerPatternType::RHOMBUS => "mr",
|
||||
BannerPatternType::SKULL => "sku",
|
||||
BannerPatternType::SMALL_STRIPES => "ss",
|
||||
BannerPatternType::SQUARE_BOTTOM_LEFT => "bl",
|
||||
BannerPatternType::SQUARE_BOTTOM_RIGHT => "br",
|
||||
BannerPatternType::SQUARE_TOP_LEFT => "tl",
|
||||
BannerPatternType::SQUARE_TOP_RIGHT => "tr",
|
||||
BannerPatternType::STRAIGHT_CROSS => "sc",
|
||||
BannerPatternType::STRIPE_BOTTOM => "bs",
|
||||
BannerPatternType::STRIPE_CENTER => "cs",
|
||||
BannerPatternType::STRIPE_DOWNLEFT => "dls",
|
||||
BannerPatternType::STRIPE_DOWNRIGHT => "drs",
|
||||
BannerPatternType::STRIPE_LEFT => "ls",
|
||||
BannerPatternType::STRIPE_MIDDLE => "ms",
|
||||
BannerPatternType::STRIPE_RIGHT => "rs",
|
||||
BannerPatternType::STRIPE_TOP => "ts",
|
||||
BannerPatternType::TRIANGLE_BOTTOM => "bt",
|
||||
BannerPatternType::TRIANGLE_TOP => "tt",
|
||||
BannerPatternType::TRIANGLES_BOTTOM => "bts",
|
||||
BannerPatternType::TRIANGLES_TOP => "tts",
|
||||
}, $case);
|
||||
}
|
||||
}
|
||||
|
||||
public function register(string $stringId, BannerPatternType $type) : void{
|
||||
|
@ -48,22 +48,28 @@ final class DyeColorIdMap{
|
||||
private array $enumToItemId = [];
|
||||
|
||||
private function __construct(){
|
||||
$this->register(0, ItemTypeNames::WHITE_DYE, DyeColor::WHITE);
|
||||
$this->register(1, ItemTypeNames::ORANGE_DYE, DyeColor::ORANGE);
|
||||
$this->register(2, ItemTypeNames::MAGENTA_DYE, DyeColor::MAGENTA);
|
||||
$this->register(3, ItemTypeNames::LIGHT_BLUE_DYE, DyeColor::LIGHT_BLUE);
|
||||
$this->register(4, ItemTypeNames::YELLOW_DYE, DyeColor::YELLOW);
|
||||
$this->register(5, ItemTypeNames::LIME_DYE, DyeColor::LIME);
|
||||
$this->register(6, ItemTypeNames::PINK_DYE, DyeColor::PINK);
|
||||
$this->register(7, ItemTypeNames::GRAY_DYE, DyeColor::GRAY);
|
||||
$this->register(8, ItemTypeNames::LIGHT_GRAY_DYE, DyeColor::LIGHT_GRAY);
|
||||
$this->register(9, ItemTypeNames::CYAN_DYE, DyeColor::CYAN);
|
||||
$this->register(10, ItemTypeNames::PURPLE_DYE, DyeColor::PURPLE);
|
||||
$this->register(11, ItemTypeNames::BLUE_DYE, DyeColor::BLUE);
|
||||
$this->register(12, ItemTypeNames::BROWN_DYE, DyeColor::BROWN);
|
||||
$this->register(13, ItemTypeNames::GREEN_DYE, DyeColor::GREEN);
|
||||
$this->register(14, ItemTypeNames::RED_DYE, DyeColor::RED);
|
||||
$this->register(15, ItemTypeNames::BLACK_DYE, DyeColor::BLACK);
|
||||
foreach(DyeColor::cases() as $case){
|
||||
[$colorId, $dyeItemId] = match($case){
|
||||
DyeColor::WHITE => [0, ItemTypeNames::WHITE_DYE],
|
||||
DyeColor::ORANGE => [1, ItemTypeNames::ORANGE_DYE],
|
||||
DyeColor::MAGENTA => [2, ItemTypeNames::MAGENTA_DYE],
|
||||
DyeColor::LIGHT_BLUE => [3, ItemTypeNames::LIGHT_BLUE_DYE],
|
||||
DyeColor::YELLOW => [4, ItemTypeNames::YELLOW_DYE],
|
||||
DyeColor::LIME => [5, ItemTypeNames::LIME_DYE],
|
||||
DyeColor::PINK => [6, ItemTypeNames::PINK_DYE],
|
||||
DyeColor::GRAY => [7, ItemTypeNames::GRAY_DYE],
|
||||
DyeColor::LIGHT_GRAY => [8, ItemTypeNames::LIGHT_GRAY_DYE],
|
||||
DyeColor::CYAN => [9, ItemTypeNames::CYAN_DYE],
|
||||
DyeColor::PURPLE => [10, ItemTypeNames::PURPLE_DYE],
|
||||
DyeColor::BLUE => [11, ItemTypeNames::BLUE_DYE],
|
||||
DyeColor::BROWN => [12, ItemTypeNames::BROWN_DYE],
|
||||
DyeColor::GREEN => [13, ItemTypeNames::GREEN_DYE],
|
||||
DyeColor::RED => [14, ItemTypeNames::RED_DYE],
|
||||
DyeColor::BLACK => [15, ItemTypeNames::BLACK_DYE],
|
||||
};
|
||||
|
||||
$this->register($colorId, $dyeItemId, $case);
|
||||
}
|
||||
}
|
||||
|
||||
private function register(int $id, string $itemId, DyeColor $color) : void{
|
||||
|
@ -32,9 +32,13 @@ final class MedicineTypeIdMap{
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(MedicineTypeIds::ANTIDOTE, MedicineType::ANTIDOTE);
|
||||
$this->register(MedicineTypeIds::ELIXIR, MedicineType::ELIXIR);
|
||||
$this->register(MedicineTypeIds::EYE_DROPS, MedicineType::EYE_DROPS);
|
||||
$this->register(MedicineTypeIds::TONIC, MedicineType::TONIC);
|
||||
foreach(MedicineType::cases() as $case){
|
||||
$this->register(match($case){
|
||||
MedicineType::ANTIDOTE => MedicineTypeIds::ANTIDOTE,
|
||||
MedicineType::ELIXIR => MedicineTypeIds::ELIXIR,
|
||||
MedicineType::EYE_DROPS => MedicineTypeIds::EYE_DROPS,
|
||||
MedicineType::TONIC => MedicineTypeIds::TONIC,
|
||||
}, $case);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,12 +32,16 @@ final class MobHeadTypeIdMap{
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(0, MobHeadType::SKELETON);
|
||||
$this->register(1, MobHeadType::WITHER_SKELETON);
|
||||
$this->register(2, MobHeadType::ZOMBIE);
|
||||
$this->register(3, MobHeadType::PLAYER);
|
||||
$this->register(4, MobHeadType::CREEPER);
|
||||
$this->register(5, MobHeadType::DRAGON);
|
||||
$this->register(6, MobHeadType::PIGLIN);
|
||||
foreach(MobHeadType::cases() as $case){
|
||||
$this->register(match($case){
|
||||
MobHeadType::SKELETON => 0,
|
||||
MobHeadType::WITHER_SKELETON => 1,
|
||||
MobHeadType::ZOMBIE => 2,
|
||||
MobHeadType::PLAYER => 3,
|
||||
MobHeadType::CREEPER => 4,
|
||||
MobHeadType::DRAGON => 5,
|
||||
MobHeadType::PIGLIN => 6,
|
||||
}, $case);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,16 +33,20 @@ final class MushroomBlockTypeIdMap{
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
public function __construct(){
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_ALL_PORES, MushroomBlockType::PORES);
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_NORTHWEST_CORNER, MushroomBlockType::CAP_NORTHWEST);
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_NORTH_SIDE, MushroomBlockType::CAP_NORTH);
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_NORTHEAST_CORNER, MushroomBlockType::CAP_NORTHEAST);
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_WEST_SIDE, MushroomBlockType::CAP_WEST);
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_TOP_ONLY, MushroomBlockType::CAP_MIDDLE);
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_EAST_SIDE, MushroomBlockType::CAP_EAST);
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHWEST_CORNER, MushroomBlockType::CAP_SOUTHWEST);
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTH_SIDE, MushroomBlockType::CAP_SOUTH);
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHEAST_CORNER, MushroomBlockType::CAP_SOUTHEAST);
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_ALL_CAP, MushroomBlockType::ALL_CAP);
|
||||
foreach(MushroomBlockType::cases() as $case){
|
||||
$this->register(match($case){
|
||||
MushroomBlockType::PORES => LegacyMeta::MUSHROOM_BLOCK_ALL_PORES,
|
||||
MushroomBlockType::CAP_NORTHWEST => LegacyMeta::MUSHROOM_BLOCK_CAP_NORTHWEST_CORNER,
|
||||
MushroomBlockType::CAP_NORTH => LegacyMeta::MUSHROOM_BLOCK_CAP_NORTH_SIDE,
|
||||
MushroomBlockType::CAP_NORTHEAST => LegacyMeta::MUSHROOM_BLOCK_CAP_NORTHEAST_CORNER,
|
||||
MushroomBlockType::CAP_WEST => LegacyMeta::MUSHROOM_BLOCK_CAP_WEST_SIDE,
|
||||
MushroomBlockType::CAP_MIDDLE => LegacyMeta::MUSHROOM_BLOCK_CAP_TOP_ONLY,
|
||||
MushroomBlockType::CAP_EAST => LegacyMeta::MUSHROOM_BLOCK_CAP_EAST_SIDE,
|
||||
MushroomBlockType::CAP_SOUTHWEST => LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHWEST_CORNER,
|
||||
MushroomBlockType::CAP_SOUTH => LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTH_SIDE,
|
||||
MushroomBlockType::CAP_SOUTHEAST => LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHEAST_CORNER,
|
||||
MushroomBlockType::ALL_CAP => LegacyMeta::MUSHROOM_BLOCK_ALL_CAP,
|
||||
}, $case);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,21 +32,25 @@ final class NoteInstrumentIdMap{
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(0, NoteInstrument::PIANO);
|
||||
$this->register(1, NoteInstrument::BASS_DRUM);
|
||||
$this->register(2, NoteInstrument::SNARE);
|
||||
$this->register(3, NoteInstrument::CLICKS_AND_STICKS);
|
||||
$this->register(4, NoteInstrument::DOUBLE_BASS);
|
||||
$this->register(5, NoteInstrument::BELL);
|
||||
$this->register(6, NoteInstrument::FLUTE);
|
||||
$this->register(7, NoteInstrument::CHIME);
|
||||
$this->register(8, NoteInstrument::GUITAR);
|
||||
$this->register(9, NoteInstrument::XYLOPHONE);
|
||||
$this->register(10, NoteInstrument::IRON_XYLOPHONE);
|
||||
$this->register(11, NoteInstrument::COW_BELL);
|
||||
$this->register(12, NoteInstrument::DIDGERIDOO);
|
||||
$this->register(13, NoteInstrument::BIT);
|
||||
$this->register(14, NoteInstrument::BANJO);
|
||||
$this->register(15, NoteInstrument::PLING);
|
||||
foreach(NoteInstrument::cases() as $case){
|
||||
$this->register(match($case){
|
||||
NoteInstrument::PIANO => 0,
|
||||
NoteInstrument::BASS_DRUM => 1,
|
||||
NoteInstrument::SNARE => 2,
|
||||
NoteInstrument::CLICKS_AND_STICKS => 3,
|
||||
NoteInstrument::DOUBLE_BASS => 4,
|
||||
NoteInstrument::BELL => 5,
|
||||
NoteInstrument::FLUTE => 6,
|
||||
NoteInstrument::CHIME => 7,
|
||||
NoteInstrument::GUITAR => 8,
|
||||
NoteInstrument::XYLOPHONE => 9,
|
||||
NoteInstrument::IRON_XYLOPHONE => 10,
|
||||
NoteInstrument::COW_BELL => 11,
|
||||
NoteInstrument::DIDGERIDOO => 12,
|
||||
NoteInstrument::BIT => 13,
|
||||
NoteInstrument::BANJO => 14,
|
||||
NoteInstrument::PLING => 15,
|
||||
}, $case);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,48 +32,52 @@ final class PotionTypeIdMap{
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(PotionTypeIds::WATER, PotionType::WATER);
|
||||
$this->register(PotionTypeIds::MUNDANE, PotionType::MUNDANE);
|
||||
$this->register(PotionTypeIds::LONG_MUNDANE, PotionType::LONG_MUNDANE);
|
||||
$this->register(PotionTypeIds::THICK, PotionType::THICK);
|
||||
$this->register(PotionTypeIds::AWKWARD, PotionType::AWKWARD);
|
||||
$this->register(PotionTypeIds::NIGHT_VISION, PotionType::NIGHT_VISION);
|
||||
$this->register(PotionTypeIds::LONG_NIGHT_VISION, PotionType::LONG_NIGHT_VISION);
|
||||
$this->register(PotionTypeIds::INVISIBILITY, PotionType::INVISIBILITY);
|
||||
$this->register(PotionTypeIds::LONG_INVISIBILITY, PotionType::LONG_INVISIBILITY);
|
||||
$this->register(PotionTypeIds::LEAPING, PotionType::LEAPING);
|
||||
$this->register(PotionTypeIds::LONG_LEAPING, PotionType::LONG_LEAPING);
|
||||
$this->register(PotionTypeIds::STRONG_LEAPING, PotionType::STRONG_LEAPING);
|
||||
$this->register(PotionTypeIds::FIRE_RESISTANCE, PotionType::FIRE_RESISTANCE);
|
||||
$this->register(PotionTypeIds::LONG_FIRE_RESISTANCE, PotionType::LONG_FIRE_RESISTANCE);
|
||||
$this->register(PotionTypeIds::SWIFTNESS, PotionType::SWIFTNESS);
|
||||
$this->register(PotionTypeIds::LONG_SWIFTNESS, PotionType::LONG_SWIFTNESS);
|
||||
$this->register(PotionTypeIds::STRONG_SWIFTNESS, PotionType::STRONG_SWIFTNESS);
|
||||
$this->register(PotionTypeIds::SLOWNESS, PotionType::SLOWNESS);
|
||||
$this->register(PotionTypeIds::LONG_SLOWNESS, PotionType::LONG_SLOWNESS);
|
||||
$this->register(PotionTypeIds::WATER_BREATHING, PotionType::WATER_BREATHING);
|
||||
$this->register(PotionTypeIds::LONG_WATER_BREATHING, PotionType::LONG_WATER_BREATHING);
|
||||
$this->register(PotionTypeIds::HEALING, PotionType::HEALING);
|
||||
$this->register(PotionTypeIds::STRONG_HEALING, PotionType::STRONG_HEALING);
|
||||
$this->register(PotionTypeIds::HARMING, PotionType::HARMING);
|
||||
$this->register(PotionTypeIds::STRONG_HARMING, PotionType::STRONG_HARMING);
|
||||
$this->register(PotionTypeIds::POISON, PotionType::POISON);
|
||||
$this->register(PotionTypeIds::LONG_POISON, PotionType::LONG_POISON);
|
||||
$this->register(PotionTypeIds::STRONG_POISON, PotionType::STRONG_POISON);
|
||||
$this->register(PotionTypeIds::REGENERATION, PotionType::REGENERATION);
|
||||
$this->register(PotionTypeIds::LONG_REGENERATION, PotionType::LONG_REGENERATION);
|
||||
$this->register(PotionTypeIds::STRONG_REGENERATION, PotionType::STRONG_REGENERATION);
|
||||
$this->register(PotionTypeIds::STRENGTH, PotionType::STRENGTH);
|
||||
$this->register(PotionTypeIds::LONG_STRENGTH, PotionType::LONG_STRENGTH);
|
||||
$this->register(PotionTypeIds::STRONG_STRENGTH, PotionType::STRONG_STRENGTH);
|
||||
$this->register(PotionTypeIds::WEAKNESS, PotionType::WEAKNESS);
|
||||
$this->register(PotionTypeIds::LONG_WEAKNESS, PotionType::LONG_WEAKNESS);
|
||||
$this->register(PotionTypeIds::WITHER, PotionType::WITHER);
|
||||
$this->register(PotionTypeIds::TURTLE_MASTER, PotionType::TURTLE_MASTER);
|
||||
$this->register(PotionTypeIds::LONG_TURTLE_MASTER, PotionType::LONG_TURTLE_MASTER);
|
||||
$this->register(PotionTypeIds::STRONG_TURTLE_MASTER, PotionType::STRONG_TURTLE_MASTER);
|
||||
$this->register(PotionTypeIds::SLOW_FALLING, PotionType::SLOW_FALLING);
|
||||
$this->register(PotionTypeIds::LONG_SLOW_FALLING, PotionType::LONG_SLOW_FALLING);
|
||||
$this->register(PotionTypeIds::STRONG_SLOWNESS, PotionType::STRONG_SLOWNESS);
|
||||
foreach(PotionType::cases() as $case){
|
||||
$this->register(match($case){
|
||||
PotionType::WATER => PotionTypeIds::WATER,
|
||||
PotionType::MUNDANE => PotionTypeIds::MUNDANE,
|
||||
PotionType::LONG_MUNDANE => PotionTypeIds::LONG_MUNDANE,
|
||||
PotionType::THICK => PotionTypeIds::THICK,
|
||||
PotionType::AWKWARD => PotionTypeIds::AWKWARD,
|
||||
PotionType::NIGHT_VISION => PotionTypeIds::NIGHT_VISION,
|
||||
PotionType::LONG_NIGHT_VISION => PotionTypeIds::LONG_NIGHT_VISION,
|
||||
PotionType::INVISIBILITY => PotionTypeIds::INVISIBILITY,
|
||||
PotionType::LONG_INVISIBILITY => PotionTypeIds::LONG_INVISIBILITY,
|
||||
PotionType::LEAPING => PotionTypeIds::LEAPING,
|
||||
PotionType::LONG_LEAPING => PotionTypeIds::LONG_LEAPING,
|
||||
PotionType::STRONG_LEAPING => PotionTypeIds::STRONG_LEAPING,
|
||||
PotionType::FIRE_RESISTANCE => PotionTypeIds::FIRE_RESISTANCE,
|
||||
PotionType::LONG_FIRE_RESISTANCE => PotionTypeIds::LONG_FIRE_RESISTANCE,
|
||||
PotionType::SWIFTNESS => PotionTypeIds::SWIFTNESS,
|
||||
PotionType::LONG_SWIFTNESS => PotionTypeIds::LONG_SWIFTNESS,
|
||||
PotionType::STRONG_SWIFTNESS => PotionTypeIds::STRONG_SWIFTNESS,
|
||||
PotionType::SLOWNESS => PotionTypeIds::SLOWNESS,
|
||||
PotionType::LONG_SLOWNESS => PotionTypeIds::LONG_SLOWNESS,
|
||||
PotionType::WATER_BREATHING => PotionTypeIds::WATER_BREATHING,
|
||||
PotionType::LONG_WATER_BREATHING => PotionTypeIds::LONG_WATER_BREATHING,
|
||||
PotionType::HEALING => PotionTypeIds::HEALING,
|
||||
PotionType::STRONG_HEALING => PotionTypeIds::STRONG_HEALING,
|
||||
PotionType::HARMING => PotionTypeIds::HARMING,
|
||||
PotionType::STRONG_HARMING => PotionTypeIds::STRONG_HARMING,
|
||||
PotionType::POISON => PotionTypeIds::POISON,
|
||||
PotionType::LONG_POISON => PotionTypeIds::LONG_POISON,
|
||||
PotionType::STRONG_POISON => PotionTypeIds::STRONG_POISON,
|
||||
PotionType::REGENERATION => PotionTypeIds::REGENERATION,
|
||||
PotionType::LONG_REGENERATION => PotionTypeIds::LONG_REGENERATION,
|
||||
PotionType::STRONG_REGENERATION => PotionTypeIds::STRONG_REGENERATION,
|
||||
PotionType::STRENGTH => PotionTypeIds::STRENGTH,
|
||||
PotionType::LONG_STRENGTH => PotionTypeIds::LONG_STRENGTH,
|
||||
PotionType::STRONG_STRENGTH => PotionTypeIds::STRONG_STRENGTH,
|
||||
PotionType::WEAKNESS => PotionTypeIds::WEAKNESS,
|
||||
PotionType::LONG_WEAKNESS => PotionTypeIds::LONG_WEAKNESS,
|
||||
PotionType::WITHER => PotionTypeIds::WITHER,
|
||||
PotionType::TURTLE_MASTER => PotionTypeIds::TURTLE_MASTER,
|
||||
PotionType::LONG_TURTLE_MASTER => PotionTypeIds::LONG_TURTLE_MASTER,
|
||||
PotionType::STRONG_TURTLE_MASTER => PotionTypeIds::STRONG_TURTLE_MASTER,
|
||||
PotionType::SLOW_FALLING => PotionTypeIds::SLOW_FALLING,
|
||||
PotionType::LONG_SLOW_FALLING => PotionTypeIds::LONG_SLOW_FALLING,
|
||||
PotionType::STRONG_SLOWNESS => PotionTypeIds::STRONG_SLOWNESS,
|
||||
}, $case);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,15 +32,20 @@ final class SuspiciousStewTypeIdMap{
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(SuspiciousStewTypeIds::POPPY, SuspiciousStewType::POPPY);
|
||||
$this->register(SuspiciousStewTypeIds::CORNFLOWER, SuspiciousStewType::CORNFLOWER);
|
||||
$this->register(SuspiciousStewTypeIds::TULIP, SuspiciousStewType::TULIP);
|
||||
$this->register(SuspiciousStewTypeIds::AZURE_BLUET, SuspiciousStewType::AZURE_BLUET);
|
||||
$this->register(SuspiciousStewTypeIds::LILY_OF_THE_VALLEY, SuspiciousStewType::LILY_OF_THE_VALLEY);
|
||||
$this->register(SuspiciousStewTypeIds::DANDELION, SuspiciousStewType::DANDELION);
|
||||
$this->register(SuspiciousStewTypeIds::BLUE_ORCHID, SuspiciousStewType::BLUE_ORCHID);
|
||||
$this->register(SuspiciousStewTypeIds::ALLIUM, SuspiciousStewType::ALLIUM);
|
||||
$this->register(SuspiciousStewTypeIds::OXEYE_DAISY, SuspiciousStewType::OXEYE_DAISY);
|
||||
$this->register(SuspiciousStewTypeIds::WITHER_ROSE, SuspiciousStewType::WITHER_ROSE);
|
||||
foreach(SuspiciousStewType::cases() as $case){
|
||||
$this->register(match($case){
|
||||
SuspiciousStewType::POPPY => SuspiciousStewTypeIds::POPPY,
|
||||
SuspiciousStewType::CORNFLOWER => SuspiciousStewTypeIds::CORNFLOWER,
|
||||
SuspiciousStewType::TULIP => SuspiciousStewTypeIds::TULIP,
|
||||
SuspiciousStewType::AZURE_BLUET => SuspiciousStewTypeIds::AZURE_BLUET,
|
||||
SuspiciousStewType::LILY_OF_THE_VALLEY => SuspiciousStewTypeIds::LILY_OF_THE_VALLEY,
|
||||
SuspiciousStewType::DANDELION => SuspiciousStewTypeIds::DANDELION,
|
||||
SuspiciousStewType::BLUE_ORCHID => SuspiciousStewTypeIds::BLUE_ORCHID,
|
||||
SuspiciousStewType::ALLIUM => SuspiciousStewTypeIds::ALLIUM,
|
||||
SuspiciousStewType::OXEYE_DAISY => SuspiciousStewTypeIds::OXEYE_DAISY,
|
||||
SuspiciousStewType::WITHER_ROSE => SuspiciousStewTypeIds::WITHER_ROSE,
|
||||
}, $case);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ final class BlockStateData{
|
||||
public const CURRENT_VERSION =
|
||||
(1 << 24) | //major
|
||||
(20 << 16) | //minor
|
||||
(40 << 8) | //patch
|
||||
(3); //revision
|
||||
(50 << 8) | //patch
|
||||
(1); //revision
|
||||
|
||||
public const TAG_NAME = "name";
|
||||
public const TAG_STATES = "states";
|
||||
|
@ -66,6 +66,7 @@ final class BlockStateNames{
|
||||
public const CORAL_HANG_TYPE_BIT = "coral_hang_type_bit";
|
||||
public const COVERED_BIT = "covered_bit";
|
||||
public const CRACKED_STATE = "cracked_state";
|
||||
public const CRAFTING = "crafting";
|
||||
public const DAMAGE = "damage";
|
||||
public const DEAD_BIT = "dead_bit";
|
||||
public const DEPRECATED = "deprecated";
|
||||
@ -109,6 +110,7 @@ final class BlockStateNames{
|
||||
public const OCCUPIED_BIT = "occupied_bit";
|
||||
public const OLD_LEAF_TYPE = "old_leaf_type";
|
||||
public const OPEN_BIT = "open_bit";
|
||||
public const ORIENTATION = "orientation";
|
||||
public const OUTPUT_LIT_BIT = "output_lit_bit";
|
||||
public const OUTPUT_SUBTRACT_BIT = "output_subtract_bit";
|
||||
public const PERSISTENT_BIT = "persistent_bit";
|
||||
@ -136,7 +138,6 @@ final class BlockStateNames{
|
||||
public const STONE_SLAB_TYPE_2 = "stone_slab_type_2";
|
||||
public const STONE_SLAB_TYPE_3 = "stone_slab_type_3";
|
||||
public const STONE_SLAB_TYPE_4 = "stone_slab_type_4";
|
||||
public const STONE_TYPE = "stone_type";
|
||||
public const STRIPPED_BIT = "stripped_bit";
|
||||
public const STRUCTURE_BLOCK_TYPE = "structure_block_type";
|
||||
public const STRUCTURE_VOID_TYPE = "structure_void_type";
|
||||
|
@ -168,6 +168,19 @@ final class BlockStateStringValues{
|
||||
public const OLD_LEAF_TYPE_OAK = "oak";
|
||||
public const OLD_LEAF_TYPE_SPRUCE = "spruce";
|
||||
|
||||
public const ORIENTATION_DOWN_EAST = "down_east";
|
||||
public const ORIENTATION_DOWN_NORTH = "down_north";
|
||||
public const ORIENTATION_DOWN_SOUTH = "down_south";
|
||||
public const ORIENTATION_DOWN_WEST = "down_west";
|
||||
public const ORIENTATION_EAST_UP = "east_up";
|
||||
public const ORIENTATION_NORTH_UP = "north_up";
|
||||
public const ORIENTATION_SOUTH_UP = "south_up";
|
||||
public const ORIENTATION_UP_EAST = "up_east";
|
||||
public const ORIENTATION_UP_NORTH = "up_north";
|
||||
public const ORIENTATION_UP_SOUTH = "up_south";
|
||||
public const ORIENTATION_UP_WEST = "up_west";
|
||||
public const ORIENTATION_WEST_UP = "west_up";
|
||||
|
||||
public const PILLAR_AXIS_X = "x";
|
||||
public const PILLAR_AXIS_Y = "y";
|
||||
public const PILLAR_AXIS_Z = "z";
|
||||
@ -241,14 +254,6 @@ final class BlockStateStringValues{
|
||||
public const STONE_SLAB_TYPE_4_SMOOTH_QUARTZ = "smooth_quartz";
|
||||
public const STONE_SLAB_TYPE_4_STONE = "stone";
|
||||
|
||||
public const STONE_TYPE_ANDESITE = "andesite";
|
||||
public const STONE_TYPE_ANDESITE_SMOOTH = "andesite_smooth";
|
||||
public const STONE_TYPE_DIORITE = "diorite";
|
||||
public const STONE_TYPE_DIORITE_SMOOTH = "diorite_smooth";
|
||||
public const STONE_TYPE_GRANITE = "granite";
|
||||
public const STONE_TYPE_GRANITE_SMOOTH = "granite_smooth";
|
||||
public const STONE_TYPE_STONE = "stone";
|
||||
|
||||
public const STRUCTURE_BLOCK_TYPE_CORNER = "corner";
|
||||
public const STRUCTURE_BLOCK_TYPE_DATA = "data";
|
||||
public const STRUCTURE_BLOCK_TYPE_EXPORT = "export";
|
||||
|
@ -37,6 +37,7 @@ final class BlockTypeNames{
|
||||
public const ACACIA_FENCE_GATE = "minecraft:acacia_fence_gate";
|
||||
public const ACACIA_HANGING_SIGN = "minecraft:acacia_hanging_sign";
|
||||
public const ACACIA_LOG = "minecraft:acacia_log";
|
||||
public const ACACIA_PLANKS = "minecraft:acacia_planks";
|
||||
public const ACACIA_PRESSURE_PLATE = "minecraft:acacia_pressure_plate";
|
||||
public const ACACIA_STAIRS = "minecraft:acacia_stairs";
|
||||
public const ACACIA_STANDING_SIGN = "minecraft:acacia_standing_sign";
|
||||
@ -48,6 +49,7 @@ final class BlockTypeNames{
|
||||
public const AMETHYST_BLOCK = "minecraft:amethyst_block";
|
||||
public const AMETHYST_CLUSTER = "minecraft:amethyst_cluster";
|
||||
public const ANCIENT_DEBRIS = "minecraft:ancient_debris";
|
||||
public const ANDESITE = "minecraft:andesite";
|
||||
public const ANDESITE_STAIRS = "minecraft:andesite_stairs";
|
||||
public const ANVIL = "minecraft:anvil";
|
||||
public const AZALEA = "minecraft:azalea";
|
||||
@ -90,6 +92,7 @@ final class BlockTypeNames{
|
||||
public const BIRCH_FENCE_GATE = "minecraft:birch_fence_gate";
|
||||
public const BIRCH_HANGING_SIGN = "minecraft:birch_hanging_sign";
|
||||
public const BIRCH_LOG = "minecraft:birch_log";
|
||||
public const BIRCH_PLANKS = "minecraft:birch_planks";
|
||||
public const BIRCH_PRESSURE_PLATE = "minecraft:birch_pressure_plate";
|
||||
public const BIRCH_STAIRS = "minecraft:birch_stairs";
|
||||
public const BIRCH_STANDING_SIGN = "minecraft:birch_standing_sign";
|
||||
@ -185,9 +188,12 @@ final class BlockTypeNames{
|
||||
public const CHERRY_WOOD = "minecraft:cherry_wood";
|
||||
public const CHEST = "minecraft:chest";
|
||||
public const CHISELED_BOOKSHELF = "minecraft:chiseled_bookshelf";
|
||||
public const CHISELED_COPPER = "minecraft:chiseled_copper";
|
||||
public const CHISELED_DEEPSLATE = "minecraft:chiseled_deepslate";
|
||||
public const CHISELED_NETHER_BRICKS = "minecraft:chiseled_nether_bricks";
|
||||
public const CHISELED_POLISHED_BLACKSTONE = "minecraft:chiseled_polished_blackstone";
|
||||
public const CHISELED_TUFF = "minecraft:chiseled_tuff";
|
||||
public const CHISELED_TUFF_BRICKS = "minecraft:chiseled_tuff_bricks";
|
||||
public const CHORUS_FLOWER = "minecraft:chorus_flower";
|
||||
public const CHORUS_PLANT = "minecraft:chorus_plant";
|
||||
public const CLAY = "minecraft:clay";
|
||||
@ -208,7 +214,11 @@ final class BlockTypeNames{
|
||||
public const COMPOSTER = "minecraft:composter";
|
||||
public const CONDUIT = "minecraft:conduit";
|
||||
public const COPPER_BLOCK = "minecraft:copper_block";
|
||||
public const COPPER_BULB = "minecraft:copper_bulb";
|
||||
public const COPPER_DOOR = "minecraft:copper_door";
|
||||
public const COPPER_GRATE = "minecraft:copper_grate";
|
||||
public const COPPER_ORE = "minecraft:copper_ore";
|
||||
public const COPPER_TRAPDOOR = "minecraft:copper_trapdoor";
|
||||
public const CORAL_BLOCK = "minecraft:coral_block";
|
||||
public const CORAL_FAN = "minecraft:coral_fan";
|
||||
public const CORAL_FAN_DEAD = "minecraft:coral_fan_dead";
|
||||
@ -219,6 +229,7 @@ final class BlockTypeNames{
|
||||
public const CRACKED_DEEPSLATE_TILES = "minecraft:cracked_deepslate_tiles";
|
||||
public const CRACKED_NETHER_BRICKS = "minecraft:cracked_nether_bricks";
|
||||
public const CRACKED_POLISHED_BLACKSTONE_BRICKS = "minecraft:cracked_polished_blackstone_bricks";
|
||||
public const CRAFTER = "minecraft:crafter";
|
||||
public const CRAFTING_TABLE = "minecraft:crafting_table";
|
||||
public const CRIMSON_BUTTON = "minecraft:crimson_button";
|
||||
public const CRIMSON_DOOR = "minecraft:crimson_door";
|
||||
@ -259,6 +270,7 @@ final class BlockTypeNames{
|
||||
public const DARK_OAK_FENCE_GATE = "minecraft:dark_oak_fence_gate";
|
||||
public const DARK_OAK_HANGING_SIGN = "minecraft:dark_oak_hanging_sign";
|
||||
public const DARK_OAK_LOG = "minecraft:dark_oak_log";
|
||||
public const DARK_OAK_PLANKS = "minecraft:dark_oak_planks";
|
||||
public const DARK_OAK_PRESSURE_PLATE = "minecraft:dark_oak_pressure_plate";
|
||||
public const DARK_OAK_STAIRS = "minecraft:dark_oak_stairs";
|
||||
public const DARK_OAK_TRAPDOOR = "minecraft:dark_oak_trapdoor";
|
||||
@ -297,6 +309,7 @@ final class BlockTypeNames{
|
||||
public const DETECTOR_RAIL = "minecraft:detector_rail";
|
||||
public const DIAMOND_BLOCK = "minecraft:diamond_block";
|
||||
public const DIAMOND_ORE = "minecraft:diamond_ore";
|
||||
public const DIORITE = "minecraft:diorite";
|
||||
public const DIORITE_STAIRS = "minecraft:diorite_stairs";
|
||||
public const DIRT = "minecraft:dirt";
|
||||
public const DIRT_WITH_ROOTS = "minecraft:dirt_with_roots";
|
||||
@ -442,7 +455,12 @@ final class BlockTypeNames{
|
||||
public const END_ROD = "minecraft:end_rod";
|
||||
public const END_STONE = "minecraft:end_stone";
|
||||
public const ENDER_CHEST = "minecraft:ender_chest";
|
||||
public const EXPOSED_CHISELED_COPPER = "minecraft:exposed_chiseled_copper";
|
||||
public const EXPOSED_COPPER = "minecraft:exposed_copper";
|
||||
public const EXPOSED_COPPER_BULB = "minecraft:exposed_copper_bulb";
|
||||
public const EXPOSED_COPPER_DOOR = "minecraft:exposed_copper_door";
|
||||
public const EXPOSED_COPPER_GRATE = "minecraft:exposed_copper_grate";
|
||||
public const EXPOSED_COPPER_TRAPDOOR = "minecraft:exposed_copper_trapdoor";
|
||||
public const EXPOSED_CUT_COPPER = "minecraft:exposed_cut_copper";
|
||||
public const EXPOSED_CUT_COPPER_SLAB = "minecraft:exposed_cut_copper_slab";
|
||||
public const EXPOSED_CUT_COPPER_STAIRS = "minecraft:exposed_cut_copper_stairs";
|
||||
@ -470,6 +488,7 @@ final class BlockTypeNames{
|
||||
public const GOLD_BLOCK = "minecraft:gold_block";
|
||||
public const GOLD_ORE = "minecraft:gold_ore";
|
||||
public const GOLDEN_RAIL = "minecraft:golden_rail";
|
||||
public const GRANITE = "minecraft:granite";
|
||||
public const GRANITE_STAIRS = "minecraft:granite_stairs";
|
||||
public const GRASS = "minecraft:grass";
|
||||
public const GRASS_PATH = "minecraft:grass_path";
|
||||
@ -527,6 +546,7 @@ final class BlockTypeNames{
|
||||
public const JUNGLE_FENCE_GATE = "minecraft:jungle_fence_gate";
|
||||
public const JUNGLE_HANGING_SIGN = "minecraft:jungle_hanging_sign";
|
||||
public const JUNGLE_LOG = "minecraft:jungle_log";
|
||||
public const JUNGLE_PLANKS = "minecraft:jungle_planks";
|
||||
public const JUNGLE_PRESSURE_PLATE = "minecraft:jungle_pressure_plate";
|
||||
public const JUNGLE_STAIRS = "minecraft:jungle_stairs";
|
||||
public const JUNGLE_STANDING_SIGN = "minecraft:jungle_standing_sign";
|
||||
@ -651,6 +671,7 @@ final class BlockTypeNames{
|
||||
public const OAK_FENCE = "minecraft:oak_fence";
|
||||
public const OAK_HANGING_SIGN = "minecraft:oak_hanging_sign";
|
||||
public const OAK_LOG = "minecraft:oak_log";
|
||||
public const OAK_PLANKS = "minecraft:oak_planks";
|
||||
public const OAK_STAIRS = "minecraft:oak_stairs";
|
||||
public const OBSERVER = "minecraft:observer";
|
||||
public const OBSIDIAN = "minecraft:obsidian";
|
||||
@ -666,7 +687,12 @@ final class BlockTypeNames{
|
||||
public const ORANGE_STAINED_GLASS_PANE = "minecraft:orange_stained_glass_pane";
|
||||
public const ORANGE_TERRACOTTA = "minecraft:orange_terracotta";
|
||||
public const ORANGE_WOOL = "minecraft:orange_wool";
|
||||
public const OXIDIZED_CHISELED_COPPER = "minecraft:oxidized_chiseled_copper";
|
||||
public const OXIDIZED_COPPER = "minecraft:oxidized_copper";
|
||||
public const OXIDIZED_COPPER_BULB = "minecraft:oxidized_copper_bulb";
|
||||
public const OXIDIZED_COPPER_DOOR = "minecraft:oxidized_copper_door";
|
||||
public const OXIDIZED_COPPER_GRATE = "minecraft:oxidized_copper_grate";
|
||||
public const OXIDIZED_COPPER_TRAPDOOR = "minecraft:oxidized_copper_trapdoor";
|
||||
public const OXIDIZED_CUT_COPPER = "minecraft:oxidized_cut_copper";
|
||||
public const OXIDIZED_CUT_COPPER_SLAB = "minecraft:oxidized_cut_copper_slab";
|
||||
public const OXIDIZED_CUT_COPPER_STAIRS = "minecraft:oxidized_cut_copper_stairs";
|
||||
@ -690,9 +716,9 @@ final class BlockTypeNames{
|
||||
public const PISTON_ARM_COLLISION = "minecraft:piston_arm_collision";
|
||||
public const PITCHER_CROP = "minecraft:pitcher_crop";
|
||||
public const PITCHER_PLANT = "minecraft:pitcher_plant";
|
||||
public const PLANKS = "minecraft:planks";
|
||||
public const PODZOL = "minecraft:podzol";
|
||||
public const POINTED_DRIPSTONE = "minecraft:pointed_dripstone";
|
||||
public const POLISHED_ANDESITE = "minecraft:polished_andesite";
|
||||
public const POLISHED_ANDESITE_STAIRS = "minecraft:polished_andesite_stairs";
|
||||
public const POLISHED_BASALT = "minecraft:polished_basalt";
|
||||
public const POLISHED_BLACKSTONE = "minecraft:polished_blackstone";
|
||||
@ -712,8 +738,15 @@ final class BlockTypeNames{
|
||||
public const POLISHED_DEEPSLATE_SLAB = "minecraft:polished_deepslate_slab";
|
||||
public const POLISHED_DEEPSLATE_STAIRS = "minecraft:polished_deepslate_stairs";
|
||||
public const POLISHED_DEEPSLATE_WALL = "minecraft:polished_deepslate_wall";
|
||||
public const POLISHED_DIORITE = "minecraft:polished_diorite";
|
||||
public const POLISHED_DIORITE_STAIRS = "minecraft:polished_diorite_stairs";
|
||||
public const POLISHED_GRANITE = "minecraft:polished_granite";
|
||||
public const POLISHED_GRANITE_STAIRS = "minecraft:polished_granite_stairs";
|
||||
public const POLISHED_TUFF = "minecraft:polished_tuff";
|
||||
public const POLISHED_TUFF_DOUBLE_SLAB = "minecraft:polished_tuff_double_slab";
|
||||
public const POLISHED_TUFF_SLAB = "minecraft:polished_tuff_slab";
|
||||
public const POLISHED_TUFF_STAIRS = "minecraft:polished_tuff_stairs";
|
||||
public const POLISHED_TUFF_WALL = "minecraft:polished_tuff_wall";
|
||||
public const PORTAL = "minecraft:portal";
|
||||
public const POTATOES = "minecraft:potatoes";
|
||||
public const POWDER_SNOW = "minecraft:powder_snow";
|
||||
@ -816,6 +849,7 @@ final class BlockTypeNames{
|
||||
public const SPRUCE_FENCE_GATE = "minecraft:spruce_fence_gate";
|
||||
public const SPRUCE_HANGING_SIGN = "minecraft:spruce_hanging_sign";
|
||||
public const SPRUCE_LOG = "minecraft:spruce_log";
|
||||
public const SPRUCE_PLANKS = "minecraft:spruce_planks";
|
||||
public const SPRUCE_PRESSURE_PLATE = "minecraft:spruce_pressure_plate";
|
||||
public const SPRUCE_STAIRS = "minecraft:spruce_stairs";
|
||||
public const SPRUCE_STANDING_SIGN = "minecraft:spruce_standing_sign";
|
||||
@ -870,6 +904,15 @@ final class BlockTypeNames{
|
||||
public const TRIPWIRE_HOOK = "minecraft:tripwire_hook";
|
||||
public const TUBE_CORAL = "minecraft:tube_coral";
|
||||
public const TUFF = "minecraft:tuff";
|
||||
public const TUFF_BRICK_DOUBLE_SLAB = "minecraft:tuff_brick_double_slab";
|
||||
public const TUFF_BRICK_SLAB = "minecraft:tuff_brick_slab";
|
||||
public const TUFF_BRICK_STAIRS = "minecraft:tuff_brick_stairs";
|
||||
public const TUFF_BRICK_WALL = "minecraft:tuff_brick_wall";
|
||||
public const TUFF_BRICKS = "minecraft:tuff_bricks";
|
||||
public const TUFF_DOUBLE_SLAB = "minecraft:tuff_double_slab";
|
||||
public const TUFF_SLAB = "minecraft:tuff_slab";
|
||||
public const TUFF_STAIRS = "minecraft:tuff_stairs";
|
||||
public const TUFF_WALL = "minecraft:tuff_wall";
|
||||
public const TURTLE_EGG = "minecraft:turtle_egg";
|
||||
public const TWISTING_VINES = "minecraft:twisting_vines";
|
||||
public const UNDERWATER_TORCH = "minecraft:underwater_torch";
|
||||
@ -903,27 +946,52 @@ final class BlockTypeNames{
|
||||
public const WARPED_WART_BLOCK = "minecraft:warped_wart_block";
|
||||
public const WATER = "minecraft:water";
|
||||
public const WATERLILY = "minecraft:waterlily";
|
||||
public const WAXED_CHISELED_COPPER = "minecraft:waxed_chiseled_copper";
|
||||
public const WAXED_COPPER = "minecraft:waxed_copper";
|
||||
public const WAXED_COPPER_BULB = "minecraft:waxed_copper_bulb";
|
||||
public const WAXED_COPPER_DOOR = "minecraft:waxed_copper_door";
|
||||
public const WAXED_COPPER_GRATE = "minecraft:waxed_copper_grate";
|
||||
public const WAXED_COPPER_TRAPDOOR = "minecraft:waxed_copper_trapdoor";
|
||||
public const WAXED_CUT_COPPER = "minecraft:waxed_cut_copper";
|
||||
public const WAXED_CUT_COPPER_SLAB = "minecraft:waxed_cut_copper_slab";
|
||||
public const WAXED_CUT_COPPER_STAIRS = "minecraft:waxed_cut_copper_stairs";
|
||||
public const WAXED_DOUBLE_CUT_COPPER_SLAB = "minecraft:waxed_double_cut_copper_slab";
|
||||
public const WAXED_EXPOSED_CHISELED_COPPER = "minecraft:waxed_exposed_chiseled_copper";
|
||||
public const WAXED_EXPOSED_COPPER = "minecraft:waxed_exposed_copper";
|
||||
public const WAXED_EXPOSED_COPPER_BULB = "minecraft:waxed_exposed_copper_bulb";
|
||||
public const WAXED_EXPOSED_COPPER_DOOR = "minecraft:waxed_exposed_copper_door";
|
||||
public const WAXED_EXPOSED_COPPER_GRATE = "minecraft:waxed_exposed_copper_grate";
|
||||
public const WAXED_EXPOSED_COPPER_TRAPDOOR = "minecraft:waxed_exposed_copper_trapdoor";
|
||||
public const WAXED_EXPOSED_CUT_COPPER = "minecraft:waxed_exposed_cut_copper";
|
||||
public const WAXED_EXPOSED_CUT_COPPER_SLAB = "minecraft:waxed_exposed_cut_copper_slab";
|
||||
public const WAXED_EXPOSED_CUT_COPPER_STAIRS = "minecraft:waxed_exposed_cut_copper_stairs";
|
||||
public const WAXED_EXPOSED_DOUBLE_CUT_COPPER_SLAB = "minecraft:waxed_exposed_double_cut_copper_slab";
|
||||
public const WAXED_OXIDIZED_CHISELED_COPPER = "minecraft:waxed_oxidized_chiseled_copper";
|
||||
public const WAXED_OXIDIZED_COPPER = "minecraft:waxed_oxidized_copper";
|
||||
public const WAXED_OXIDIZED_COPPER_BULB = "minecraft:waxed_oxidized_copper_bulb";
|
||||
public const WAXED_OXIDIZED_COPPER_DOOR = "minecraft:waxed_oxidized_copper_door";
|
||||
public const WAXED_OXIDIZED_COPPER_GRATE = "minecraft:waxed_oxidized_copper_grate";
|
||||
public const WAXED_OXIDIZED_COPPER_TRAPDOOR = "minecraft:waxed_oxidized_copper_trapdoor";
|
||||
public const WAXED_OXIDIZED_CUT_COPPER = "minecraft:waxed_oxidized_cut_copper";
|
||||
public const WAXED_OXIDIZED_CUT_COPPER_SLAB = "minecraft:waxed_oxidized_cut_copper_slab";
|
||||
public const WAXED_OXIDIZED_CUT_COPPER_STAIRS = "minecraft:waxed_oxidized_cut_copper_stairs";
|
||||
public const WAXED_OXIDIZED_DOUBLE_CUT_COPPER_SLAB = "minecraft:waxed_oxidized_double_cut_copper_slab";
|
||||
public const WAXED_WEATHERED_CHISELED_COPPER = "minecraft:waxed_weathered_chiseled_copper";
|
||||
public const WAXED_WEATHERED_COPPER = "minecraft:waxed_weathered_copper";
|
||||
public const WAXED_WEATHERED_COPPER_BULB = "minecraft:waxed_weathered_copper_bulb";
|
||||
public const WAXED_WEATHERED_COPPER_DOOR = "minecraft:waxed_weathered_copper_door";
|
||||
public const WAXED_WEATHERED_COPPER_GRATE = "minecraft:waxed_weathered_copper_grate";
|
||||
public const WAXED_WEATHERED_COPPER_TRAPDOOR = "minecraft:waxed_weathered_copper_trapdoor";
|
||||
public const WAXED_WEATHERED_CUT_COPPER = "minecraft:waxed_weathered_cut_copper";
|
||||
public const WAXED_WEATHERED_CUT_COPPER_SLAB = "minecraft:waxed_weathered_cut_copper_slab";
|
||||
public const WAXED_WEATHERED_CUT_COPPER_STAIRS = "minecraft:waxed_weathered_cut_copper_stairs";
|
||||
public const WAXED_WEATHERED_DOUBLE_CUT_COPPER_SLAB = "minecraft:waxed_weathered_double_cut_copper_slab";
|
||||
public const WEATHERED_CHISELED_COPPER = "minecraft:weathered_chiseled_copper";
|
||||
public const WEATHERED_COPPER = "minecraft:weathered_copper";
|
||||
public const WEATHERED_COPPER_BULB = "minecraft:weathered_copper_bulb";
|
||||
public const WEATHERED_COPPER_DOOR = "minecraft:weathered_copper_door";
|
||||
public const WEATHERED_COPPER_GRATE = "minecraft:weathered_copper_grate";
|
||||
public const WEATHERED_COPPER_TRAPDOOR = "minecraft:weathered_copper_trapdoor";
|
||||
public const WEATHERED_CUT_COPPER = "minecraft:weathered_cut_copper";
|
||||
public const WEATHERED_CUT_COPPER_SLAB = "minecraft:weathered_cut_copper_slab";
|
||||
public const WEATHERED_CUT_COPPER_STAIRS = "minecraft:weathered_cut_copper_stairs";
|
||||
|
@ -521,7 +521,8 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->map(Blocks::ACACIA_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::ACACIA_WALL_SIGN)));
|
||||
$this->mapLog(Blocks::ACACIA_LOG(), Ids::ACACIA_LOG, Ids::STRIPPED_ACACIA_LOG);
|
||||
$this->mapSimple(Blocks::ACACIA_FENCE(), Ids::ACACIA_FENCE);
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
$this->mapSimple(Blocks::ACACIA_PLANKS(), Ids::ACACIA_PLANKS);
|
||||
//wood and slabs still use the old way of storing wood type
|
||||
|
||||
$this->map(Blocks::BIRCH_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::BIRCH_BUTTON)));
|
||||
$this->map(Blocks::BIRCH_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::BIRCH_DOOR)));
|
||||
@ -532,8 +533,9 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->map(Blocks::BIRCH_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::BIRCH_WALL_SIGN)));
|
||||
$this->mapLog(Blocks::BIRCH_LOG(), Ids::BIRCH_LOG, Ids::STRIPPED_BIRCH_LOG);
|
||||
$this->mapSimple(Blocks::BIRCH_FENCE(), Ids::BIRCH_FENCE);
|
||||
$this->mapSimple(Blocks::BIRCH_PLANKS(), Ids::BIRCH_PLANKS);
|
||||
$this->mapStairs(Blocks::BIRCH_STAIRS(), Ids::BIRCH_STAIRS);
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
//wood and slabs still use the old way of storing wood type
|
||||
|
||||
$this->map(Blocks::CHERRY_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::CHERRY_BUTTON)));
|
||||
$this->map(Blocks::CHERRY_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::CHERRY_DOOR)));
|
||||
@ -582,8 +584,9 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->map(Blocks::DARK_OAK_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::DARKOAK_WALL_SIGN)));
|
||||
$this->mapLog(Blocks::DARK_OAK_LOG(), Ids::DARK_OAK_LOG, Ids::STRIPPED_DARK_OAK_LOG);
|
||||
$this->mapSimple(Blocks::DARK_OAK_FENCE(), Ids::DARK_OAK_FENCE);
|
||||
$this->mapSimple(Blocks::DARK_OAK_PLANKS(), Ids::DARK_OAK_PLANKS);
|
||||
$this->mapStairs(Blocks::DARK_OAK_STAIRS(), Ids::DARK_OAK_STAIRS);
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
//wood and slabs still use the old way of storing wood type
|
||||
|
||||
$this->map(Blocks::JUNGLE_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::JUNGLE_BUTTON)));
|
||||
$this->map(Blocks::JUNGLE_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::JUNGLE_DOOR)));
|
||||
@ -594,8 +597,9 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->map(Blocks::JUNGLE_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::JUNGLE_WALL_SIGN)));
|
||||
$this->mapLog(Blocks::JUNGLE_LOG(), Ids::JUNGLE_LOG, Ids::STRIPPED_JUNGLE_LOG);
|
||||
$this->mapSimple(Blocks::JUNGLE_FENCE(), Ids::JUNGLE_FENCE);
|
||||
$this->mapSimple(Blocks::JUNGLE_PLANKS(), Ids::JUNGLE_PLANKS);
|
||||
$this->mapStairs(Blocks::JUNGLE_STAIRS(), Ids::JUNGLE_STAIRS);
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
//wood and slabs still use the old way of storing wood type
|
||||
|
||||
$this->map(Blocks::MANGROVE_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::MANGROVE_BUTTON)));
|
||||
$this->map(Blocks::MANGROVE_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::MANGROVE_DOOR)));
|
||||
@ -630,20 +634,22 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->map(Blocks::OAK_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::WALL_SIGN)));
|
||||
$this->mapLog(Blocks::OAK_LOG(), Ids::OAK_LOG, Ids::STRIPPED_OAK_LOG);
|
||||
$this->mapSimple(Blocks::OAK_FENCE(), Ids::OAK_FENCE);
|
||||
$this->mapSimple(Blocks::OAK_PLANKS(), Ids::OAK_PLANKS);
|
||||
$this->mapStairs(Blocks::OAK_STAIRS(), Ids::OAK_STAIRS);
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
//wood and slabs still use the old way of storing wood type
|
||||
|
||||
$this->mapSimple(Blocks::SPRUCE_FENCE(), Ids::SPRUCE_FENCE);
|
||||
$this->mapLog(Blocks::SPRUCE_LOG(), Ids::SPRUCE_LOG, Ids::STRIPPED_SPRUCE_LOG);
|
||||
$this->map(Blocks::SPRUCE_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::SPRUCE_BUTTON)));
|
||||
$this->map(Blocks::SPRUCE_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::SPRUCE_DOOR)));
|
||||
$this->map(Blocks::SPRUCE_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::SPRUCE_FENCE_GATE)));
|
||||
$this->map(Blocks::SPRUCE_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::SPRUCE_PRESSURE_PLATE)));
|
||||
$this->map(Blocks::SPRUCE_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::SPRUCE_STANDING_SIGN)));
|
||||
$this->mapStairs(Blocks::SPRUCE_STAIRS(), Ids::SPRUCE_STAIRS);
|
||||
$this->map(Blocks::SPRUCE_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::SPRUCE_TRAPDOOR)));
|
||||
$this->map(Blocks::SPRUCE_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::SPRUCE_WALL_SIGN)));
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
$this->mapLog(Blocks::SPRUCE_LOG(), Ids::SPRUCE_LOG, Ids::STRIPPED_SPRUCE_LOG);
|
||||
$this->mapSimple(Blocks::SPRUCE_FENCE(), Ids::SPRUCE_FENCE);
|
||||
$this->mapSimple(Blocks::SPRUCE_PLANKS(), Ids::SPRUCE_PLANKS);
|
||||
$this->mapStairs(Blocks::SPRUCE_STAIRS(), Ids::SPRUCE_STAIRS);
|
||||
//wood and slabs still use the old way of storing wood type
|
||||
|
||||
$this->map(Blocks::WARPED_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::WARPED_BUTTON)));
|
||||
$this->map(Blocks::WARPED_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::WARPED_DOOR)));
|
||||
@ -661,18 +667,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
}
|
||||
|
||||
private function registerLegacyWoodBlockSerializers() : void{
|
||||
foreach([
|
||||
StringValues::WOOD_TYPE_ACACIA => Blocks::ACACIA_PLANKS(),
|
||||
StringValues::WOOD_TYPE_BIRCH => Blocks::BIRCH_PLANKS(),
|
||||
StringValues::WOOD_TYPE_DARK_OAK => Blocks::DARK_OAK_PLANKS(),
|
||||
StringValues::WOOD_TYPE_JUNGLE => Blocks::JUNGLE_PLANKS(),
|
||||
StringValues::WOOD_TYPE_OAK => Blocks::OAK_PLANKS(),
|
||||
StringValues::WOOD_TYPE_SPRUCE => Blocks::SPRUCE_PLANKS(),
|
||||
] as $woodType => $block){
|
||||
$this->map($block, fn() => Writer::create(Ids::PLANKS)
|
||||
->writeString(StateNames::WOOD_TYPE, $woodType));
|
||||
}
|
||||
|
||||
foreach([
|
||||
StringValues::WOOD_TYPE_ACACIA => Blocks::ACACIA_SLAB(),
|
||||
StringValues::WOOD_TYPE_BIRCH => Blocks::BIRCH_SLAB(),
|
||||
@ -716,6 +710,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::AIR(), Ids::AIR);
|
||||
$this->mapSimple(Blocks::AMETHYST(), Ids::AMETHYST_BLOCK);
|
||||
$this->mapSimple(Blocks::ANCIENT_DEBRIS(), Ids::ANCIENT_DEBRIS);
|
||||
$this->mapSimple(Blocks::ANDESITE(), Ids::ANDESITE);
|
||||
$this->mapSimple(Blocks::BARRIER(), Ids::BARRIER);
|
||||
$this->mapSimple(Blocks::BEACON(), Ids::BEACON);
|
||||
$this->mapSimple(Blocks::BLACKSTONE(), Ids::BLACKSTONE);
|
||||
@ -758,6 +753,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::DEEPSLATE_TILES(), Ids::DEEPSLATE_TILES);
|
||||
$this->mapSimple(Blocks::DIAMOND(), Ids::DIAMOND_BLOCK);
|
||||
$this->mapSimple(Blocks::DIAMOND_ORE(), Ids::DIAMOND_ORE);
|
||||
$this->mapSimple(Blocks::DIORITE(), Ids::DIORITE);
|
||||
$this->mapSimple(Blocks::DRAGON_EGG(), Ids::DRAGON_EGG);
|
||||
$this->mapSimple(Blocks::DRIED_KELP(), Ids::DRIED_KELP_BLOCK);
|
||||
$this->mapSimple(Blocks::ELEMENT_ACTINIUM(), Ids::ELEMENT_89);
|
||||
@ -892,6 +888,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::GLOWSTONE(), Ids::GLOWSTONE);
|
||||
$this->mapSimple(Blocks::GOLD(), Ids::GOLD_BLOCK);
|
||||
$this->mapSimple(Blocks::GOLD_ORE(), Ids::GOLD_ORE);
|
||||
$this->mapSimple(Blocks::GRANITE(), Ids::GRANITE);
|
||||
$this->mapSimple(Blocks::GRASS(), Ids::GRASS);
|
||||
$this->mapSimple(Blocks::GRASS_PATH(), Ids::GRASS_PATH);
|
||||
$this->mapSimple(Blocks::GRAVEL(), Ids::GRAVEL);
|
||||
@ -933,9 +930,12 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::PACKED_ICE(), Ids::PACKED_ICE);
|
||||
$this->mapSimple(Blocks::PACKED_MUD(), Ids::PACKED_MUD);
|
||||
$this->mapSimple(Blocks::PODZOL(), Ids::PODZOL);
|
||||
$this->mapSimple(Blocks::POLISHED_ANDESITE(), Ids::POLISHED_ANDESITE);
|
||||
$this->mapSimple(Blocks::POLISHED_BLACKSTONE(), Ids::POLISHED_BLACKSTONE);
|
||||
$this->mapSimple(Blocks::POLISHED_BLACKSTONE_BRICKS(), Ids::POLISHED_BLACKSTONE_BRICKS);
|
||||
$this->mapSimple(Blocks::POLISHED_DEEPSLATE(), Ids::POLISHED_DEEPSLATE);
|
||||
$this->mapSimple(Blocks::POLISHED_DIORITE(), Ids::POLISHED_DIORITE);
|
||||
$this->mapSimple(Blocks::POLISHED_GRANITE(), Ids::POLISHED_GRANITE);
|
||||
$this->mapSimple(Blocks::QUARTZ_BRICKS(), Ids::QUARTZ_BRICKS);
|
||||
$this->mapSimple(Blocks::RAW_COPPER(), Ids::RAW_COPPER_BLOCK);
|
||||
$this->mapSimple(Blocks::RAW_GOLD(), Ids::RAW_GOLD_BLOCK);
|
||||
@ -957,6 +957,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::SOUL_SAND(), Ids::SOUL_SAND);
|
||||
$this->mapSimple(Blocks::SOUL_SOIL(), Ids::SOUL_SOIL);
|
||||
$this->mapSimple(Blocks::SPORE_BLOSSOM(), Ids::SPORE_BLOSSOM);
|
||||
$this->mapSimple(Blocks::STONE(), Ids::STONE);
|
||||
$this->mapSimple(Blocks::TINTED_GLASS(), Ids::TINTED_GLASS);
|
||||
$this->mapSimple(Blocks::TORCHFLOWER(), Ids::TORCHFLOWER);
|
||||
$this->mapSimple(Blocks::TUFF(), Ids::TUFF);
|
||||
@ -985,7 +986,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
})
|
||||
->writeBlockFace($block->getFacing())
|
||||
);
|
||||
$this->map(Blocks::ANDESITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_ANDESITE));
|
||||
$this->map(Blocks::ANDESITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_ANDESITE));
|
||||
$this->map(Blocks::ANDESITE_STAIRS(), fn(Stair $block) => Helper::encodeStairs($block, new Writer(Ids::ANDESITE_STAIRS)));
|
||||
$this->map(Blocks::ANDESITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_ANDESITE));
|
||||
@ -1268,7 +1268,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeBool(StateNames::RAIL_DATA_BIT, $block->isActivated())
|
||||
->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
|
||||
});
|
||||
$this->map(Blocks::DIORITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_DIORITE));
|
||||
$this->map(Blocks::DIORITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_DIORITE));
|
||||
$this->mapStairs(Blocks::DIORITE_STAIRS(), Ids::DIORITE_STAIRS);
|
||||
$this->map(Blocks::DIORITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_DIORITE));
|
||||
@ -1335,7 +1334,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeFacingFlags($block->getFaces());
|
||||
});
|
||||
$this->map(Blocks::GLOWING_ITEM_FRAME(), fn(ItemFrame $block) => Helper::encodeItemFrame($block, Ids::GLOW_FRAME));
|
||||
$this->map(Blocks::GRANITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_GRANITE));
|
||||
$this->map(Blocks::GRANITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_GRANITE));
|
||||
$this->mapStairs(Blocks::GRANITE_STAIRS(), Ids::GRANITE_STAIRS);
|
||||
$this->map(Blocks::GRANITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_GRANITE));
|
||||
@ -1473,7 +1471,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeInt(StateNames::GROWTH, $block->getAge() + 1 + PitcherCrop::MAX_AGE)
|
||||
->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop());
|
||||
});
|
||||
$this->map(Blocks::POLISHED_ANDESITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_ANDESITE_SMOOTH));
|
||||
$this->map(Blocks::POLISHED_ANDESITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_ANDESITE));
|
||||
$this->mapStairs(Blocks::POLISHED_ANDESITE_STAIRS(), Ids::POLISHED_ANDESITE_STAIRS);
|
||||
$this->map(Blocks::POLISHED_BASALT(), function(SimplePillar $block) : Writer{
|
||||
@ -1491,10 +1488,8 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSlab(Blocks::POLISHED_DEEPSLATE_SLAB(), Ids::POLISHED_DEEPSLATE_SLAB, Ids::POLISHED_DEEPSLATE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::POLISHED_DEEPSLATE_STAIRS(), Ids::POLISHED_DEEPSLATE_STAIRS);
|
||||
$this->map(Blocks::POLISHED_DEEPSLATE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::POLISHED_DEEPSLATE_WALL)));
|
||||
$this->map(Blocks::POLISHED_DIORITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_DIORITE_SMOOTH));
|
||||
$this->map(Blocks::POLISHED_DIORITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_DIORITE));
|
||||
$this->mapStairs(Blocks::POLISHED_DIORITE_STAIRS(), Ids::POLISHED_DIORITE_STAIRS);
|
||||
$this->map(Blocks::POLISHED_GRANITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_GRANITE_SMOOTH));
|
||||
$this->map(Blocks::POLISHED_GRANITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_GRANITE));
|
||||
$this->mapStairs(Blocks::POLISHED_GRANITE_STAIRS(), Ids::POLISHED_GRANITE_STAIRS);
|
||||
$this->map(Blocks::POPPY(), fn() => Helper::encodeRedFlower(StringValues::FLOWER_TYPE_POPPY));
|
||||
@ -1630,7 +1625,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
return Writer::create(Ids::HARD_STAINED_GLASS_PANE)
|
||||
->writeColor($block->getColor());
|
||||
});
|
||||
$this->map(Blocks::STONE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_STONE));
|
||||
$this->map(Blocks::STONECUTTER(), fn(Stonecutter $block) => Writer::create(Ids::STONECUTTER_BLOCK)
|
||||
->writeCardinalHorizontalFacing($block->getFacing()));
|
||||
$this->map(Blocks::STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_DEFAULT));
|
||||
|
@ -228,11 +228,6 @@ final class BlockStateSerializerHelper{
|
||||
->writeFacingWithoutUp($facing === Facing::UP ? Facing::DOWN : $facing);
|
||||
}
|
||||
|
||||
public static function encodeStone(string $type) : BlockStateWriter{
|
||||
return BlockStateWriter::create(Ids::STONE)
|
||||
->writeString(BlockStateNames::STONE_TYPE, $type);
|
||||
}
|
||||
|
||||
public static function encodeStoneBricks(string $type) : BlockStateWriter{
|
||||
return BlockStateWriter::create(Ids::STONEBRICK)
|
||||
->writeString(BlockStateNames::STONE_BRICK_TYPE, $type);
|
||||
|
@ -427,6 +427,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::ACACIA_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::ACACIA_WALL_SIGN(), $in));
|
||||
$this->mapLog(Ids::ACACIA_LOG, Ids::STRIPPED_ACACIA_LOG, fn() => Blocks::ACACIA_LOG());
|
||||
$this->mapSimple(Ids::ACACIA_FENCE, fn() => Blocks::ACACIA_FENCE());
|
||||
$this->mapSimple(Ids::ACACIA_PLANKS, fn() => Blocks::ACACIA_PLANKS());
|
||||
$this->mapStairs(Ids::ACACIA_STAIRS, fn() => Blocks::ACACIA_STAIRS());
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
|
||||
@ -439,6 +440,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::BIRCH_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::BIRCH_WALL_SIGN(), $in));
|
||||
$this->mapLog(Ids::BIRCH_LOG, Ids::STRIPPED_BIRCH_LOG, fn() => Blocks::BIRCH_LOG());
|
||||
$this->mapSimple(Ids::BIRCH_FENCE, fn() => Blocks::BIRCH_FENCE());
|
||||
$this->mapSimple(Ids::BIRCH_PLANKS, fn() => Blocks::BIRCH_PLANKS());
|
||||
$this->mapStairs(Ids::BIRCH_STAIRS, fn() => Blocks::BIRCH_STAIRS());
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
|
||||
@ -483,6 +485,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::DARK_OAK_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::DARK_OAK_TRAPDOOR(), $in));
|
||||
$this->mapLog(Ids::DARK_OAK_LOG, Ids::STRIPPED_DARK_OAK_LOG, fn() => Blocks::DARK_OAK_LOG());
|
||||
$this->mapSimple(Ids::DARK_OAK_FENCE, fn() => Blocks::DARK_OAK_FENCE());
|
||||
$this->mapSimple(Ids::DARK_OAK_PLANKS, fn() => Blocks::DARK_OAK_PLANKS());
|
||||
$this->mapStairs(Ids::DARK_OAK_STAIRS, fn() => Blocks::DARK_OAK_STAIRS());
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
|
||||
@ -495,6 +498,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::JUNGLE_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::JUNGLE_WALL_SIGN(), $in));
|
||||
$this->mapLog(Ids::JUNGLE_LOG, Ids::STRIPPED_JUNGLE_LOG, fn() => Blocks::JUNGLE_LOG());
|
||||
$this->mapSimple(Ids::JUNGLE_FENCE, fn() => Blocks::JUNGLE_FENCE());
|
||||
$this->mapSimple(Ids::JUNGLE_PLANKS, fn() => Blocks::JUNGLE_PLANKS());
|
||||
$this->mapStairs(Ids::JUNGLE_STAIRS, fn() => Blocks::JUNGLE_STAIRS());
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
|
||||
@ -526,6 +530,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::OAK_WALL_SIGN(), $in));
|
||||
$this->mapLog(Ids::OAK_LOG, Ids::STRIPPED_OAK_LOG, fn() => Blocks::OAK_LOG());
|
||||
$this->mapSimple(Ids::OAK_FENCE, fn() => Blocks::OAK_FENCE());
|
||||
$this->mapSimple(Ids::OAK_PLANKS, fn() => Blocks::OAK_PLANKS());
|
||||
$this->mapStairs(Ids::OAK_STAIRS, fn() => Blocks::OAK_STAIRS());
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
|
||||
@ -538,6 +543,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::SPRUCE_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::SPRUCE_WALL_SIGN(), $in));
|
||||
$this->mapLog(Ids::SPRUCE_LOG, Ids::STRIPPED_SPRUCE_LOG, fn() => Blocks::SPRUCE_LOG());
|
||||
$this->mapSimple(Ids::SPRUCE_FENCE, fn() => Blocks::SPRUCE_FENCE());
|
||||
$this->mapSimple(Ids::SPRUCE_PLANKS, fn() => Blocks::SPRUCE_PLANKS());
|
||||
$this->mapStairs(Ids::SPRUCE_STAIRS, fn() => Blocks::SPRUCE_STAIRS());
|
||||
//wood, planks and slabs still use the old way of storing wood type
|
||||
|
||||
@ -557,18 +563,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
}
|
||||
|
||||
private function registerLegacyWoodBlockDeserializers() : void{
|
||||
|
||||
$this->map(Ids::PLANKS, function(Reader $in) : Block{
|
||||
return match($woodName = $in->readString(StateNames::WOOD_TYPE)){
|
||||
StringValues::WOOD_TYPE_OAK => Blocks::OAK_PLANKS(),
|
||||
StringValues::WOOD_TYPE_SPRUCE => Blocks::SPRUCE_PLANKS(),
|
||||
StringValues::WOOD_TYPE_BIRCH => Blocks::BIRCH_PLANKS(),
|
||||
StringValues::WOOD_TYPE_JUNGLE => Blocks::JUNGLE_PLANKS(),
|
||||
StringValues::WOOD_TYPE_ACACIA => Blocks::ACACIA_PLANKS(),
|
||||
StringValues::WOOD_TYPE_DARK_OAK => Blocks::DARK_OAK_PLANKS(),
|
||||
default => throw $in->badValueException(StateNames::WOOD_TYPE, $woodName),
|
||||
};
|
||||
});
|
||||
$this->mapSlab(Ids::WOODEN_SLAB, Ids::DOUBLE_WOODEN_SLAB, fn(Reader $in) => Helper::mapWoodenSlabType($in));
|
||||
|
||||
$this->map(Ids::WOOD, fn(Reader $in) : Block => Helper::decodeLog(match($woodType = $in->readString(StateNames::WOOD_TYPE)){
|
||||
@ -608,6 +602,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::AIR, fn() => Blocks::AIR());
|
||||
$this->mapSimple(Ids::AMETHYST_BLOCK, fn() => Blocks::AMETHYST());
|
||||
$this->mapSimple(Ids::ANCIENT_DEBRIS, fn() => Blocks::ANCIENT_DEBRIS());
|
||||
$this->mapSimple(Ids::ANDESITE, fn() => Blocks::ANDESITE());
|
||||
$this->mapSimple(Ids::BARRIER, fn() => Blocks::BARRIER());
|
||||
$this->mapSimple(Ids::BEACON, fn() => Blocks::BEACON());
|
||||
$this->mapSimple(Ids::BLACKSTONE, fn() => Blocks::BLACKSTONE());
|
||||
@ -648,6 +643,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::DEEPSLATE_TILES, fn() => Blocks::DEEPSLATE_TILES());
|
||||
$this->mapSimple(Ids::DIAMOND_BLOCK, fn() => Blocks::DIAMOND());
|
||||
$this->mapSimple(Ids::DIAMOND_ORE, fn() => Blocks::DIAMOND_ORE());
|
||||
$this->mapSimple(Ids::DIORITE, fn() => Blocks::DIORITE());
|
||||
$this->mapSimple(Ids::DRAGON_EGG, fn() => Blocks::DRAGON_EGG());
|
||||
$this->mapSimple(Ids::DRIED_KELP_BLOCK, fn() => Blocks::DRIED_KELP());
|
||||
$this->mapSimple(Ids::ELEMENT_0, fn() => Blocks::ELEMENT_ZERO());
|
||||
@ -782,6 +778,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::GLOWSTONE, fn() => Blocks::GLOWSTONE());
|
||||
$this->mapSimple(Ids::GOLD_BLOCK, fn() => Blocks::GOLD());
|
||||
$this->mapSimple(Ids::GOLD_ORE, fn() => Blocks::GOLD_ORE());
|
||||
$this->mapSimple(Ids::GRANITE, fn() => Blocks::GRANITE());
|
||||
$this->mapSimple(Ids::GRASS, fn() => Blocks::GRASS());
|
||||
$this->mapSimple(Ids::GRASS_PATH, fn() => Blocks::GRASS_PATH());
|
||||
$this->mapSimple(Ids::GRAVEL, fn() => Blocks::GRAVEL());
|
||||
@ -820,9 +817,12 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::PACKED_ICE, fn() => Blocks::PACKED_ICE());
|
||||
$this->mapSimple(Ids::PACKED_MUD, fn() => Blocks::PACKED_MUD());
|
||||
$this->mapSimple(Ids::PODZOL, fn() => Blocks::PODZOL());
|
||||
$this->mapSimple(Ids::POLISHED_ANDESITE, fn() => Blocks::POLISHED_ANDESITE());
|
||||
$this->mapSimple(Ids::POLISHED_BLACKSTONE, fn() => Blocks::POLISHED_BLACKSTONE());
|
||||
$this->mapSimple(Ids::POLISHED_BLACKSTONE_BRICKS, fn() => Blocks::POLISHED_BLACKSTONE_BRICKS());
|
||||
$this->mapSimple(Ids::POLISHED_DEEPSLATE, fn() => Blocks::POLISHED_DEEPSLATE());
|
||||
$this->mapSimple(Ids::POLISHED_DIORITE, fn() => Blocks::POLISHED_DIORITE());
|
||||
$this->mapSimple(Ids::POLISHED_GRANITE, fn() => Blocks::POLISHED_GRANITE());
|
||||
$this->mapSimple(Ids::QUARTZ_BRICKS, fn() => Blocks::QUARTZ_BRICKS());
|
||||
$this->mapSimple(Ids::QUARTZ_ORE, fn() => Blocks::NETHER_QUARTZ_ORE());
|
||||
$this->mapSimple(Ids::RAW_COPPER_BLOCK, fn() => Blocks::RAW_COPPER());
|
||||
@ -844,6 +844,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::SOUL_SAND, fn() => Blocks::SOUL_SAND());
|
||||
$this->mapSimple(Ids::SOUL_SOIL, fn() => Blocks::SOUL_SOIL());
|
||||
$this->mapSimple(Ids::SPORE_BLOSSOM, fn() => Blocks::SPORE_BLOSSOM());
|
||||
$this->mapSimple(Ids::STONE, fn() => Blocks::STONE());
|
||||
$this->mapSimple(Ids::STONECUTTER, fn() => Blocks::LEGACY_STONECUTTER());
|
||||
$this->mapSimple(Ids::TINTED_GLASS, fn() => Blocks::TINTED_GLASS());
|
||||
$this->mapSimple(Ids::TORCHFLOWER, fn() => Blocks::TORCHFLOWER());
|
||||
@ -1528,18 +1529,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
return Blocks::BANNER()
|
||||
->setRotation($in->readBoundedInt(StateNames::GROUND_SIGN_DIRECTION, 0, 15));
|
||||
});
|
||||
$this->map(Ids::STONE, function(Reader $in) : Block{
|
||||
return match($type = $in->readString(StateNames::STONE_TYPE)){
|
||||
StringValues::STONE_TYPE_ANDESITE => Blocks::ANDESITE(),
|
||||
StringValues::STONE_TYPE_ANDESITE_SMOOTH => Blocks::POLISHED_ANDESITE(),
|
||||
StringValues::STONE_TYPE_DIORITE => Blocks::DIORITE(),
|
||||
StringValues::STONE_TYPE_DIORITE_SMOOTH => Blocks::POLISHED_DIORITE(),
|
||||
StringValues::STONE_TYPE_GRANITE => Blocks::GRANITE(),
|
||||
StringValues::STONE_TYPE_GRANITE_SMOOTH => Blocks::POLISHED_GRANITE(),
|
||||
StringValues::STONE_TYPE_STONE => Blocks::STONE(),
|
||||
default => throw $in->badValueException(StateNames::STONE_TYPE, $type),
|
||||
};
|
||||
});
|
||||
$this->mapStairs(Ids::STONE_BRICK_STAIRS, fn() => Blocks::STONE_BRICK_STAIRS());
|
||||
$this->map(Ids::STONE_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::STONE_BUTTON(), $in));
|
||||
$this->map(Ids::STONE_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::STONE_PRESSURE_PLATE(), $in));
|
||||
|
@ -147,7 +147,6 @@ final class ItemSerializerDeserializerRegistrar{
|
||||
$this->map1to1Block(Ids::JUNGLE_DOOR, Blocks::JUNGLE_DOOR());
|
||||
$this->map1to1Block(Ids::MANGROVE_DOOR, Blocks::MANGROVE_DOOR());
|
||||
$this->map1to1Block(Ids::NETHER_WART, Blocks::NETHER_WART());
|
||||
$this->map1to1Block(Ids::PITCHER_POD, Blocks::PITCHER_CROP());
|
||||
$this->map1to1Block(Ids::REPEATER, Blocks::REDSTONE_REPEATER());
|
||||
$this->map1to1Block(Ids::SPRUCE_DOOR, Blocks::SPRUCE_DOOR());
|
||||
$this->map1to1Block(Ids::SUGAR_CANE, Blocks::SUGARCANE());
|
||||
@ -326,6 +325,7 @@ final class ItemSerializerDeserializerRegistrar{
|
||||
$this->map1to1Item(Ids::PAINTING, Items::PAINTING());
|
||||
$this->map1to1Item(Ids::PAPER, Items::PAPER());
|
||||
$this->map1to1Item(Ids::PHANTOM_MEMBRANE, Items::PHANTOM_MEMBRANE());
|
||||
$this->map1to1Item(Ids::PITCHER_POD, Items::PITCHER_POD());
|
||||
$this->map1to1Item(Ids::POISONOUS_POTATO, Items::POISONOUS_POTATO());
|
||||
$this->map1to1Item(Ids::POPPED_CHORUS_FRUIT, Items::POPPED_CHORUS_FRUIT());
|
||||
$this->map1to1Item(Ids::PORKCHOP, Items::RAW_PORKCHOP());
|
||||
|
@ -134,6 +134,7 @@ final class ItemTypeNames{
|
||||
public const COOKED_RABBIT = "minecraft:cooked_rabbit";
|
||||
public const COOKED_SALMON = "minecraft:cooked_salmon";
|
||||
public const COOKIE = "minecraft:cookie";
|
||||
public const COPPER_DOOR = "minecraft:copper_door";
|
||||
public const COPPER_INGOT = "minecraft:copper_ingot";
|
||||
public const CORAL = "minecraft:coral";
|
||||
public const COW_SPAWN_EGG = "minecraft:cow_spawn_egg";
|
||||
@ -150,6 +151,7 @@ final class ItemTypeNames{
|
||||
public const DARK_OAK_DOOR = "minecraft:dark_oak_door";
|
||||
public const DARK_OAK_HANGING_SIGN = "minecraft:dark_oak_hanging_sign";
|
||||
public const DARK_OAK_SIGN = "minecraft:dark_oak_sign";
|
||||
public const DEBUG_STICK = "minecraft:debug_stick";
|
||||
public const DIAMOND = "minecraft:diamond";
|
||||
public const DIAMOND_AXE = "minecraft:diamond_axe";
|
||||
public const DIAMOND_BOOTS = "minecraft:diamond_boots";
|
||||
@ -186,6 +188,7 @@ final class ItemTypeNames{
|
||||
public const EVOKER_SPAWN_EGG = "minecraft:evoker_spawn_egg";
|
||||
public const EXPERIENCE_BOTTLE = "minecraft:experience_bottle";
|
||||
public const EXPLORER_POTTERY_SHERD = "minecraft:explorer_pottery_sherd";
|
||||
public const EXPOSED_COPPER_DOOR = "minecraft:exposed_copper_door";
|
||||
public const EYE_ARMOR_TRIM_SMITHING_TEMPLATE = "minecraft:eye_armor_trim_smithing_template";
|
||||
public const FEATHER = "minecraft:feather";
|
||||
public const FENCE = "minecraft:fence";
|
||||
@ -347,6 +350,7 @@ final class ItemTypeNames{
|
||||
public const OAK_SIGN = "minecraft:oak_sign";
|
||||
public const OCELOT_SPAWN_EGG = "minecraft:ocelot_spawn_egg";
|
||||
public const ORANGE_DYE = "minecraft:orange_dye";
|
||||
public const OXIDIZED_COPPER_DOOR = "minecraft:oxidized_copper_door";
|
||||
public const PAINTING = "minecraft:painting";
|
||||
public const PANDA_SPAWN_EGG = "minecraft:panda_spawn_egg";
|
||||
public const PAPER = "minecraft:paper";
|
||||
@ -360,6 +364,7 @@ final class ItemTypeNames{
|
||||
public const PILLAGER_SPAWN_EGG = "minecraft:pillager_spawn_egg";
|
||||
public const PINK_DYE = "minecraft:pink_dye";
|
||||
public const PITCHER_POD = "minecraft:pitcher_pod";
|
||||
public const PLANKS = "minecraft:planks";
|
||||
public const PLENTY_POTTERY_SHERD = "minecraft:plenty_pottery_sherd";
|
||||
public const POISONOUS_POTATO = "minecraft:poisonous_potato";
|
||||
public const POLAR_BEAR_SPAWN_EGG = "minecraft:polar_bear_spawn_egg";
|
||||
@ -479,7 +484,12 @@ final class ItemTypeNames{
|
||||
public const WARPED_HANGING_SIGN = "minecraft:warped_hanging_sign";
|
||||
public const WARPED_SIGN = "minecraft:warped_sign";
|
||||
public const WATER_BUCKET = "minecraft:water_bucket";
|
||||
public const WAXED_COPPER_DOOR = "minecraft:waxed_copper_door";
|
||||
public const WAXED_EXPOSED_COPPER_DOOR = "minecraft:waxed_exposed_copper_door";
|
||||
public const WAXED_OXIDIZED_COPPER_DOOR = "minecraft:waxed_oxidized_copper_door";
|
||||
public const WAXED_WEATHERED_COPPER_DOOR = "minecraft:waxed_weathered_copper_door";
|
||||
public const WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE = "minecraft:wayfinder_armor_trim_smithing_template";
|
||||
public const WEATHERED_COPPER_DOOR = "minecraft:weathered_copper_door";
|
||||
public const WHEAT = "minecraft:wheat";
|
||||
public const WHEAT_SEEDS = "minecraft:wheat_seeds";
|
||||
public const WHITE_DYE = "minecraft:white_dye";
|
||||
|
@ -44,10 +44,14 @@ final class GameModeIdMap{
|
||||
private array $enumToId = [];
|
||||
|
||||
public function __construct(){
|
||||
$this->register(0, GameMode::SURVIVAL);
|
||||
$this->register(1, GameMode::CREATIVE);
|
||||
$this->register(2, GameMode::ADVENTURE);
|
||||
$this->register(3, GameMode::SPECTATOR);
|
||||
foreach(GameMode::cases() as $case){
|
||||
$this->register(match($case){
|
||||
GameMode::SURVIVAL => 0,
|
||||
GameMode::CREATIVE => 1,
|
||||
GameMode::ADVENTURE => 2,
|
||||
GameMode::SPECTATOR => 3,
|
||||
}, $case);
|
||||
}
|
||||
}
|
||||
|
||||
private function register(int $id, GameMode $type) : void{
|
||||
|
@ -29,11 +29,6 @@ namespace pocketmine\data\runtime;
|
||||
* @deprecated
|
||||
*/
|
||||
trait LegacyRuntimeEnumDescriberTrait{
|
||||
|
||||
/**
|
||||
* @phpstan-template T of \UnitEnum
|
||||
* @phpstan-param T $case
|
||||
*/
|
||||
abstract protected function enum(\UnitEnum &$case) : void;
|
||||
|
||||
public function bellAttachmentType(\pocketmine\block\utils\BellAttachmentType &$value) : void{
|
||||
|
@ -89,10 +89,6 @@ interface RuntimeDataDescriber extends RuntimeEnumDescriber{
|
||||
|
||||
public function straightOnlyRailShape(int &$railShape) : void;
|
||||
|
||||
/**
|
||||
* @phpstan-template T of \UnitEnum
|
||||
* @phpstan-param T $case
|
||||
*/
|
||||
public function enum(\UnitEnum &$case) : void;
|
||||
|
||||
/**
|
||||
|
@ -173,8 +173,9 @@ abstract class Projectile extends Entity{
|
||||
$entityHit = null;
|
||||
$hitResult = null;
|
||||
|
||||
$world = $this->getWorld();
|
||||
foreach(VoxelRayTrace::betweenPoints($start, $end) as $vector3){
|
||||
$block = $this->getWorld()->getBlockAt($vector3->x, $vector3->y, $vector3->z);
|
||||
$block = $world->getBlockAt($vector3->x, $vector3->y, $vector3->z);
|
||||
|
||||
$blockHitResult = $this->calculateInterceptWithBlock($block, $start, $end);
|
||||
if($blockHitResult !== null){
|
||||
@ -188,7 +189,7 @@ abstract class Projectile extends Entity{
|
||||
$entityDistance = PHP_INT_MAX;
|
||||
|
||||
$newDiff = $end->subtractVector($start);
|
||||
foreach($this->getWorld()->getCollidingEntities($this->boundingBox->addCoord($newDiff->x, $newDiff->y, $newDiff->z)->expand(1, 1, 1), $this) as $entity){
|
||||
foreach($world->getCollidingEntities($this->boundingBox->addCoord($newDiff->x, $newDiff->y, $newDiff->z)->expand(1, 1, 1), $this) as $entity){
|
||||
if($entity->getId() === $this->getOwningEntityId() && $this->ticksLived < 5){
|
||||
continue;
|
||||
}
|
||||
@ -256,7 +257,7 @@ abstract class Projectile extends Entity{
|
||||
);
|
||||
}
|
||||
|
||||
$this->getWorld()->onEntityMoved($this);
|
||||
$world->onEntityMoved($this);
|
||||
$this->checkBlockIntersections();
|
||||
|
||||
Timings::$projectileMove->stopTiming();
|
||||
|
@ -31,8 +31,9 @@ class Snowball extends Throwable{
|
||||
public static function getNetworkTypeId() : string{ return EntityIds::SNOWBALL; }
|
||||
|
||||
protected function onHit(ProjectileHitEvent $event) : void{
|
||||
$world = $this->getWorld();
|
||||
for($i = 0; $i < 6; ++$i){
|
||||
$this->getWorld()->addParticle($this->location, new SnowballPoofParticle());
|
||||
$world->addParticle($this->location, new SnowballPoofParticle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,7 @@ class HandlerList{
|
||||
private array $affectedHandlerCaches = [];
|
||||
|
||||
/**
|
||||
* @phpstan-template TEvent of Event
|
||||
* @phpstan-param class-string<TEvent> $class
|
||||
* @phpstan-param class-string<covariant Event> $class
|
||||
*/
|
||||
public function __construct(
|
||||
private string $class,
|
||||
|
@ -113,8 +113,7 @@ class HandlerListManager{
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-template TEvent of Event
|
||||
* @phpstan-param class-string<TEvent> $event
|
||||
* @phpstan-param class-string<covariant Event> $event
|
||||
*
|
||||
* @return RegisteredListener[]
|
||||
*/
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\item;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockTypeIds;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
|
||||
/**
|
||||
@ -58,4 +59,12 @@ final class ItemBlock extends Item{
|
||||
public function getMaxStackSize() : int{
|
||||
return $this->block->getMaxStackSize();
|
||||
}
|
||||
|
||||
public function isNull() : bool{
|
||||
//TODO: we really shouldn't need to treat air as a special case here
|
||||
//this is needed because the "null" empty slot item is represented by an air block, but there's no real reason
|
||||
//why air should be needed at all. A separate special item type (or actual null) should be used instead, but
|
||||
//this would cause a lot of BC breaks, so we can't do it yet.
|
||||
return parent::isNull() || $this->block->getTypeId() === BlockTypeIds::AIR;
|
||||
}
|
||||
}
|
||||
|
@ -322,8 +322,9 @@ final class ItemTypeIds{
|
||||
public const RIB_ARMOR_TRIM_SMITHING_TEMPLATE = 20283;
|
||||
public const EYE_ARMOR_TRIM_SMITHING_TEMPLATE = 20284;
|
||||
public const SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE = 20285;
|
||||
public const PITCHER_POD = 20286;
|
||||
|
||||
public const FIRST_UNUSED_ITEM_ID = 20286;
|
||||
public const FIRST_UNUSED_ITEM_ID = 20287;
|
||||
|
||||
private static int $nextDynamicId = self::FIRST_UNUSED_ITEM_ID;
|
||||
|
||||
|
@ -21,18 +21,14 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\bedrock;
|
||||
namespace pocketmine\item;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\VanillaBlocks;
|
||||
|
||||
class DyeColorIdMapTest extends TestCase{
|
||||
final class PitcherPod extends Item{
|
||||
|
||||
public function testAllColorsMapped() : void{
|
||||
foreach(DyeColor::cases() as $color){
|
||||
$id = DyeColorIdMap::getInstance()->toId($color);
|
||||
$color2 = DyeColorIdMap::getInstance()->fromId($id);
|
||||
self::assertTrue($color === $color2);
|
||||
}
|
||||
public function getBlock(?int $clickedFace = null) : Block{
|
||||
return VanillaBlocks::PITCHER_CROP();
|
||||
}
|
||||
}
|
@ -868,6 +868,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->registerBlock("pink_petals", fn() => Blocks::PINK_PETALS());
|
||||
$result->registerBlock("pink_tulip", fn() => Blocks::PINK_TULIP());
|
||||
$result->registerBlock("piglin_head", fn() => Blocks::MOB_HEAD()->setMobHeadType(MobHeadType::PIGLIN));
|
||||
$result->registerBlock("pitcher_plant", fn() => Blocks::PITCHER_PLANT());
|
||||
$result->registerBlock("plank", fn() => Blocks::OAK_PLANKS());
|
||||
$result->registerBlock("planks", fn() => Blocks::OAK_PLANKS());
|
||||
$result->registerBlock("player_head", fn() => Blocks::MOB_HEAD()->setMobHeadType(MobHeadType::PLAYER));
|
||||
@ -1405,6 +1406,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->register("painting", fn() => Items::PAINTING());
|
||||
$result->register("paper", fn() => Items::PAPER());
|
||||
$result->register("phantom_membrane", fn() => Items::PHANTOM_MEMBRANE());
|
||||
$result->register("pitcher_pod", fn() => Items::PITCHER_POD());
|
||||
$result->register("poisonous_potato", fn() => Items::POISONOUS_POTATO());
|
||||
$result->register("popped_chorus_fruit", fn() => Items::POPPED_CHORUS_FRUIT());
|
||||
$result->register("porkchop", fn() => Items::RAW_PORKCHOP());
|
||||
|
@ -240,6 +240,7 @@ use function strtolower;
|
||||
* @method static PaintingItem PAINTING()
|
||||
* @method static Item PAPER()
|
||||
* @method static Item PHANTOM_MEMBRANE()
|
||||
* @method static PitcherPod PITCHER_POD()
|
||||
* @method static PoisonousPotato POISONOUS_POTATO()
|
||||
* @method static Item POPPED_CHORUS_FRUIT()
|
||||
* @method static Potato POTATO()
|
||||
@ -503,6 +504,7 @@ final class VanillaItems{
|
||||
self::register("painting", new PaintingItem(new IID(Ids::PAINTING), "Painting"));
|
||||
self::register("paper", new Item(new IID(Ids::PAPER), "Paper"));
|
||||
self::register("phantom_membrane", new Item(new IID(Ids::PHANTOM_MEMBRANE), "Phantom Membrane"));
|
||||
self::register("pitcher_pod", new PitcherPod(new IID(Ids::PITCHER_POD), "Pitcher Pod"));
|
||||
self::register("poisonous_potato", new PoisonousPotato(new IID(Ids::POISONOUS_POTATO), "Poisonous Potato"));
|
||||
self::register("popped_chorus_fruit", new Item(new IID(Ids::POPPED_CHORUS_FRUIT), "Popped Chorus Fruit"));
|
||||
self::register("potato", new Potato(new IID(Ids::POTATO), "Potato"));
|
||||
|
@ -117,6 +117,7 @@ use function count;
|
||||
use function get_class;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function is_string;
|
||||
use function json_encode;
|
||||
use function random_bytes;
|
||||
use function str_split;
|
||||
@ -158,8 +159,8 @@ class NetworkSession{
|
||||
private array $sendBuffer = [];
|
||||
|
||||
/**
|
||||
* @var \SplQueue|CompressBatchPromise[]
|
||||
* @phpstan-var \SplQueue<CompressBatchPromise>
|
||||
* @var \SplQueue|CompressBatchPromise[]|string[]
|
||||
* @phpstan-var \SplQueue<CompressBatchPromise|string>
|
||||
*/
|
||||
private \SplQueue $compressedQueue;
|
||||
private bool $forceAsyncCompression = true;
|
||||
@ -235,8 +236,10 @@ class NetworkSession{
|
||||
$this->onPlayerCreated(...),
|
||||
function() : void{
|
||||
//TODO: this should never actually occur... right?
|
||||
$this->logger->error("Failed to create player");
|
||||
$this->disconnectWithError(KnownTranslationFactory::pocketmine_disconnect_error_internal());
|
||||
$this->disconnectWithError(
|
||||
reason: "Failed to create player",
|
||||
disconnectScreenMessage: KnownTranslationFactory::pocketmine_disconnect_error_internal()
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -525,13 +528,12 @@ class NetworkSession{
|
||||
PacketBatch::encodeRaw($stream, $this->sendBuffer);
|
||||
|
||||
if($this->enableCompression){
|
||||
$promise = $this->server->prepareBatch($stream->getBuffer(), $this->compressor, $syncMode, Timings::$playerNetworkSendCompressSessionBuffer);
|
||||
$batch = $this->server->prepareBatch($stream->getBuffer(), $this->compressor, $syncMode, Timings::$playerNetworkSendCompressSessionBuffer);
|
||||
}else{
|
||||
$promise = new CompressBatchPromise();
|
||||
$promise->resolve($stream->getBuffer());
|
||||
$batch = $stream->getBuffer();
|
||||
}
|
||||
$this->sendBuffer = [];
|
||||
$this->queueCompressedNoBufferFlush($promise, $immediate);
|
||||
$this->queueCompressedNoBufferFlush($batch, $immediate);
|
||||
}finally{
|
||||
Timings::$playerNetworkSend->stopTiming();
|
||||
}
|
||||
@ -550,7 +552,7 @@ class NetworkSession{
|
||||
|
||||
public function getTypeConverter() : TypeConverter{ return $this->typeConverter; }
|
||||
|
||||
public function queueCompressed(CompressBatchPromise $payload, bool $immediate = false) : void{
|
||||
public function queueCompressed(CompressBatchPromise|string $payload, bool $immediate = false) : void{
|
||||
Timings::$playerNetworkSend->startTiming();
|
||||
try{
|
||||
$this->flushSendBuffer($immediate); //Maintain ordering if possible
|
||||
@ -560,36 +562,25 @@ class NetworkSession{
|
||||
}
|
||||
}
|
||||
|
||||
private function queueCompressedNoBufferFlush(CompressBatchPromise $payload, bool $immediate = false) : void{
|
||||
private function queueCompressedNoBufferFlush(CompressBatchPromise|string $batch, bool $immediate = false) : void{
|
||||
Timings::$playerNetworkSend->startTiming();
|
||||
try{
|
||||
if($immediate){
|
||||
if(is_string($batch)){
|
||||
if($immediate){
|
||||
//Skips all queues
|
||||
$this->sendEncoded($batch, true);
|
||||
}else{
|
||||
$this->compressedQueue->enqueue($batch);
|
||||
$this->flushCompressedQueue();
|
||||
}
|
||||
}elseif($immediate){
|
||||
//Skips all queues
|
||||
$this->sendEncoded($payload->getResult(), true);
|
||||
$this->sendEncoded($batch->getResult(), true);
|
||||
}else{
|
||||
$this->compressedQueue->enqueue($payload);
|
||||
$payload->onResolve(function(CompressBatchPromise $payload) : void{
|
||||
if($this->connected && $this->compressedQueue->bottom() === $payload){
|
||||
Timings::$playerNetworkSend->startTiming();
|
||||
try{
|
||||
$this->compressedQueue->dequeue(); //result unused
|
||||
$this->sendEncoded($payload->getResult());
|
||||
|
||||
while(!$this->compressedQueue->isEmpty()){
|
||||
/** @var CompressBatchPromise $current */
|
||||
$current = $this->compressedQueue->bottom();
|
||||
if($current->hasResult()){
|
||||
$this->compressedQueue->dequeue();
|
||||
|
||||
$this->sendEncoded($current->getResult());
|
||||
}else{
|
||||
//can't send any more queued until this one is ready
|
||||
break;
|
||||
}
|
||||
}
|
||||
}finally{
|
||||
Timings::$playerNetworkSend->stopTiming();
|
||||
}
|
||||
$this->compressedQueue->enqueue($batch);
|
||||
$batch->onResolve(function() : void{
|
||||
if($this->connected){
|
||||
$this->flushCompressedQueue();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -598,6 +589,30 @@ class NetworkSession{
|
||||
}
|
||||
}
|
||||
|
||||
private function flushCompressedQueue() : void{
|
||||
Timings::$playerNetworkSend->startTiming();
|
||||
try{
|
||||
while(!$this->compressedQueue->isEmpty()){
|
||||
/** @var CompressBatchPromise|string $current */
|
||||
$current = $this->compressedQueue->bottom();
|
||||
if(is_string($current)){
|
||||
$this->compressedQueue->dequeue();
|
||||
$this->sendEncoded($current);
|
||||
|
||||
}elseif($current->hasResult()){
|
||||
$this->compressedQueue->dequeue();
|
||||
$this->sendEncoded($current->getResult());
|
||||
|
||||
}else{
|
||||
//can't send any more queued until this one is ready
|
||||
break;
|
||||
}
|
||||
}
|
||||
}finally{
|
||||
Timings::$playerNetworkSend->stopTiming();
|
||||
}
|
||||
}
|
||||
|
||||
private function sendEncoded(string $payload, bool $immediate = false) : void{
|
||||
if($this->cipher !== null){
|
||||
Timings::$playerNetworkSendEncrypt->startTiming();
|
||||
@ -662,8 +677,13 @@ class NetworkSession{
|
||||
}, $reason);
|
||||
}
|
||||
|
||||
public function disconnectWithError(Translatable|string $reason) : void{
|
||||
$this->disconnect(KnownTranslationFactory::pocketmine_disconnect_error($reason, implode("-", str_split(bin2hex(random_bytes(6)), 4))));
|
||||
public function disconnectWithError(Translatable|string $reason, Translatable|string|null $disconnectScreenMessage = null) : void{
|
||||
$errorId = implode("-", str_split(bin2hex(random_bytes(6)), 4));
|
||||
|
||||
$this->disconnect(
|
||||
reason: KnownTranslationFactory::pocketmine_disconnect_error($reason, $errorId)->prefix(TextFormat::RED),
|
||||
disconnectScreenMessage: KnownTranslationFactory::pocketmine_disconnect_error($disconnectScreenMessage ?? $reason, $errorId),
|
||||
);
|
||||
}
|
||||
|
||||
public function disconnectIncompatibleProtocol(int $protocolVersion) : void{
|
||||
@ -722,7 +742,10 @@ class NetworkSession{
|
||||
}
|
||||
|
||||
if($error !== null){
|
||||
$this->disconnectWithError(KnownTranslationFactory::pocketmine_disconnect_invalidSession($error));
|
||||
$this->disconnectWithError(
|
||||
reason: KnownTranslationFactory::pocketmine_disconnect_invalidSession($error),
|
||||
disconnectScreenMessage: KnownTranslationFactory::pocketmine_disconnect_error_authentication()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1118,12 +1141,12 @@ class NetworkSession{
|
||||
*/
|
||||
public function syncPlayerList(array $players) : void{
|
||||
$this->sendDataPacket(PlayerListPacket::add(array_map(function(Player $player) : PlayerListEntry{
|
||||
return PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), TypeConverter::getInstance()->getSkinAdapter()->toSkinData($player->getSkin()), $player->getXuid());
|
||||
return PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $this->typeConverter->getSkinAdapter()->toSkinData($player->getSkin()), $player->getXuid());
|
||||
}, $players)));
|
||||
}
|
||||
|
||||
public function onPlayerAdded(Player $p) : void{
|
||||
$this->sendDataPacket(PlayerListPacket::add([PlayerListEntry::createAdditionEntry($p->getUniqueId(), $p->getId(), $p->getDisplayName(), TypeConverter::getInstance()->getSkinAdapter()->toSkinData($p->getSkin()), $p->getXuid())]));
|
||||
$this->sendDataPacket(PlayerListPacket::add([PlayerListEntry::createAdditionEntry($p->getUniqueId(), $p->getId(), $p->getDisplayName(), $this->typeConverter->getSkinAdapter()->toSkinData($p->getSkin()), $p->getXuid())]));
|
||||
}
|
||||
|
||||
public function onPlayerRemoved(Player $p) : void{
|
||||
|
@ -88,9 +88,9 @@ final class StandardPacketBroadcaster implements PacketBroadcaster{
|
||||
PacketBatch::encodeRaw($stream, $packetBuffers);
|
||||
$batchBuffer = $stream->getBuffer();
|
||||
|
||||
$promise = $this->server->prepareBatch($batchBuffer, $compressor, timings: Timings::$playerNetworkSendCompressBroadcast);
|
||||
$batch = $this->server->prepareBatch($batchBuffer, $compressor, timings: Timings::$playerNetworkSendCompressBroadcast);
|
||||
foreach($compressorTargets as $target){
|
||||
$target->queueCompressed($promise);
|
||||
$target->queueCompressed($batch);
|
||||
}
|
||||
}else{
|
||||
foreach($compressorTargets as $target){
|
||||
|
@ -39,16 +39,6 @@ use function time;
|
||||
class ProcessLoginTask extends AsyncTask{
|
||||
private const TLS_KEY_ON_COMPLETION = "completion";
|
||||
|
||||
/**
|
||||
* Old Mojang root auth key. This was used since the introduction of Xbox Live authentication in 0.15.0.
|
||||
* This key is expected to be replaced by the key below in the future, but this has not yet happened as of
|
||||
* 2023-07-01.
|
||||
* Ideally we would place a time expiry on this key, but since Mojang have not given a hard date for the key change,
|
||||
* and one bad guess has already caused a major outage, we can't do this.
|
||||
* TODO: This needs to be removed as soon as the new key is deployed by Mojang's authentication servers.
|
||||
*/
|
||||
public const MOJANG_OLD_ROOT_PUBLIC_KEY = "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8ELkixyLcwlZryUQcu1TvPOmI2B7vX83ndnWRUaXm74wFfa5f/lwQNTfrLVHa2PmenpGI6JhIMUJaWZrjmMj90NoKNFSNBuKdm8rYiXsfaz3K36x/1U26HpG0ZxK/V1V";
|
||||
|
||||
/**
|
||||
* New Mojang root auth key. Mojang notified third-party developers of this change prior to the release of 1.20.0.
|
||||
* Expectations were that this would be used starting a "couple of weeks" after the release, but as of 2023-07-01,
|
||||
@ -128,7 +118,6 @@ class ProcessLoginTask extends AsyncTask{
|
||||
try{
|
||||
[$headersArray, $claimsArray, ] = JwtUtils::parse($jwt);
|
||||
}catch(JwtException $e){
|
||||
//TODO: we shouldn't be showing internal information like this to the client
|
||||
throw new VerifyLoginException("Failed to parse JWT: " . $e->getMessage(), null, 0, $e);
|
||||
}
|
||||
|
||||
@ -141,13 +130,11 @@ class ProcessLoginTask extends AsyncTask{
|
||||
/** @var JwtHeader $headers */
|
||||
$headers = $mapper->map($headersArray, new JwtHeader());
|
||||
}catch(\JsonMapper_Exception $e){
|
||||
//TODO: we shouldn't be showing internal information like this to the client
|
||||
throw new VerifyLoginException("Invalid JWT header: " . $e->getMessage(), null, 0, $e);
|
||||
}
|
||||
|
||||
$headerDerKey = base64_decode($headers->x5u, true);
|
||||
if($headerDerKey === false){
|
||||
//TODO: we shouldn't be showing internal information like this to the client
|
||||
throw new VerifyLoginException("Invalid JWT public key: base64 decoding error decoding x5u");
|
||||
}
|
||||
|
||||
@ -163,7 +150,6 @@ class ProcessLoginTask extends AsyncTask{
|
||||
try{
|
||||
$signingKeyOpenSSL = JwtUtils::parseDerPublicKey($headerDerKey);
|
||||
}catch(JwtException $e){
|
||||
//TODO: we shouldn't be showing this internal information to the client
|
||||
throw new VerifyLoginException("Invalid JWT public key: " . $e->getMessage(), null, 0, $e);
|
||||
}
|
||||
try{
|
||||
@ -174,7 +160,7 @@ class ProcessLoginTask extends AsyncTask{
|
||||
throw new VerifyLoginException($e->getMessage(), null, 0, $e);
|
||||
}
|
||||
|
||||
if($headers->x5u === self::MOJANG_ROOT_PUBLIC_KEY || $headers->x5u === self::MOJANG_OLD_ROOT_PUBLIC_KEY){
|
||||
if($headers->x5u === self::MOJANG_ROOT_PUBLIC_KEY){
|
||||
$this->authenticated = true; //we're signed into xbox live
|
||||
}
|
||||
|
||||
|
25
src/network/mcpe/cache/ChunkCache.php
vendored
25
src/network/mcpe/cache/ChunkCache.php
vendored
@ -136,32 +136,19 @@ class ChunkCache implements ChunkListener{
|
||||
return $existing !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts an async request for an unresolved chunk.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function restartPendingRequest(int $chunkX, int $chunkZ) : void{
|
||||
$chunkHash = World::chunkHash($chunkX, $chunkZ);
|
||||
$existing = $this->caches[$chunkHash] ?? null;
|
||||
if($existing === null || $existing->hasResult()){
|
||||
throw new \InvalidArgumentException("Restart can only be applied to unresolved promises");
|
||||
}
|
||||
$existing->cancel();
|
||||
unset($this->caches[$chunkHash]);
|
||||
|
||||
$this->request($chunkX, $chunkZ)->onResolve(...$existing->getResolveCallbacks());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function destroyOrRestart(int $chunkX, int $chunkZ) : void{
|
||||
$cache = $this->caches[World::chunkHash($chunkX, $chunkZ)] ?? null;
|
||||
$chunkPosHash = World::chunkHash($chunkX, $chunkZ);
|
||||
$cache = $this->caches[$chunkPosHash] ?? null;
|
||||
if($cache !== null){
|
||||
if(!$cache->hasResult()){
|
||||
//some requesters are waiting for this chunk, so their request needs to be fulfilled
|
||||
$this->restartPendingRequest($chunkX, $chunkZ);
|
||||
$cache->cancel();
|
||||
unset($this->caches[$chunkPosHash]);
|
||||
|
||||
$this->request($chunkX, $chunkZ)->onResolve(...$cache->getResolveCallbacks());
|
||||
}else{
|
||||
//dump the cache, it'll be regenerated the next time it's requested
|
||||
$this->destroy($chunkX, $chunkZ);
|
||||
|
2
src/network/mcpe/cache/CraftingDataCache.php
vendored
2
src/network/mcpe/cache/CraftingDataCache.php
vendored
@ -160,7 +160,7 @@ final class CraftingDataCache{
|
||||
}
|
||||
|
||||
$potionContainerChangeRecipes = [];
|
||||
$itemTypeDictionary = TypeConverter::getInstance()->getItemTypeDictionary();
|
||||
$itemTypeDictionary = $converter->getItemTypeDictionary();
|
||||
foreach($manager->getPotionContainerChangeRecipes() as $recipe){
|
||||
$input = $itemTypeDictionary->fromStringId($recipe->getInputItemId());
|
||||
$ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient())->getDescriptor();
|
||||
|
@ -57,7 +57,6 @@ use pocketmine\network\mcpe\protocol\BossEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
|
||||
use pocketmine\network\mcpe\protocol\CommandRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
|
||||
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\EmotePacket;
|
||||
use pocketmine\network\mcpe\protocol\InteractPacket;
|
||||
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
|
||||
@ -731,10 +730,6 @@ class InGamePacketHandler extends PacketHandler{
|
||||
return true; //this packet is useless
|
||||
}
|
||||
|
||||
public function handleCraftingEvent(CraftingEventPacket $packet) : bool{
|
||||
return true; //this is a broken useless packet, so we don't use it
|
||||
}
|
||||
|
||||
public function handleBlockActorData(BlockActorDataPacket $packet) : bool{
|
||||
$pos = new Vector3($packet->blockPosition->getX(), $packet->blockPosition->getY(), $packet->blockPosition->getZ());
|
||||
if($pos->distanceSquared($this->player->getLocation()) > 10000){
|
||||
|
@ -73,8 +73,10 @@ class LoginPacketHandler extends PacketHandler{
|
||||
try{
|
||||
$skin = $this->session->getTypeConverter()->getSkinAdapter()->fromSkinData(ClientDataToSkinDataHelper::fromClientData($clientData));
|
||||
}catch(\InvalidArgumentException | InvalidSkinException $e){
|
||||
$this->session->getLogger()->debug("Invalid skin: " . $e->getMessage());
|
||||
$this->session->disconnectWithError(KnownTranslationFactory::disconnectionScreen_invalidSkin());
|
||||
$this->session->disconnectWithError(
|
||||
reason: "Invalid skin: " . $e->getMessage(),
|
||||
disconnectScreenMessage: KnownTranslationFactory::disconnectionScreen_invalidSkin()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -85,8 +85,10 @@ class ResourcePacksPacketHandler extends PacketHandler{
|
||||
}
|
||||
|
||||
private function disconnectWithError(string $error) : void{
|
||||
$this->session->getLogger()->error("Error downloading resource packs: " . $error);
|
||||
$this->session->disconnectWithError(KnownTranslationFactory::disconnectionScreen_resourcePack());
|
||||
$this->session->disconnectWithError(
|
||||
reason: "Error downloading resource packs: " . $error,
|
||||
disconnectScreenMessage: KnownTranslationFactory::disconnectionScreen_resourcePack()
|
||||
);
|
||||
}
|
||||
|
||||
public function handleResourcePackClientResponse(ResourcePackClientResponsePacket $packet) : bool{
|
||||
|
@ -219,11 +219,14 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
|
||||
$session->handleEncoded($buf);
|
||||
}catch(PacketHandlingException $e){
|
||||
$logger = $session->getLogger();
|
||||
$logger->error("Bad packet: " . $e->getMessage());
|
||||
|
||||
$session->disconnectWithError(
|
||||
reason: "Bad packet: " . $e->getMessage(),
|
||||
disconnectScreenMessage: KnownTranslationFactory::pocketmine_disconnect_error_badPacket()
|
||||
);
|
||||
//intentionally doesn't use logException, we don't want spammy packet error traces to appear in release mode
|
||||
$logger->debug(implode("\n", Utils::printableExceptionInfo($e)));
|
||||
$session->disconnectWithError(KnownTranslationFactory::pocketmine_disconnect_error_badPacket());
|
||||
|
||||
$this->interface->blockAddress($address, 5);
|
||||
}catch(\Throwable $e){
|
||||
//record the name of the player who caused the crash, to make it easier to find the reproducing steps
|
||||
|
@ -815,13 +815,13 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
$this->usedChunks[$index] = UsedChunkStatus::REQUESTED_GENERATION;
|
||||
$this->activeChunkGenerationRequests[$index] = true;
|
||||
unset($this->loadQueue[$index]);
|
||||
$this->getWorld()->registerChunkLoader($this->chunkLoader, $X, $Z, true);
|
||||
$this->getWorld()->registerChunkListener($this, $X, $Z);
|
||||
$world->registerChunkLoader($this->chunkLoader, $X, $Z, true);
|
||||
$world->registerChunkListener($this, $X, $Z);
|
||||
if(isset($this->tickingChunks[$index])){
|
||||
$this->getWorld()->registerTickingChunk($this->chunkTicker, $X, $Z);
|
||||
$world->registerTickingChunk($this->chunkTicker, $X, $Z);
|
||||
}
|
||||
|
||||
$this->getWorld()->requestChunkPopulation($X, $Z, $this->chunkLoader)->onCompletion(
|
||||
$world->requestChunkPopulation($X, $Z, $this->chunkLoader)->onCompletion(
|
||||
function() use ($X, $Z, $index, $world) : void{
|
||||
if(!$this->isConnected() || !isset($this->usedChunks[$index]) || $world !== $this->getWorld()){
|
||||
return;
|
||||
|
@ -70,7 +70,7 @@ abstract class PluginBase implements Plugin, CommandExecutor{
|
||||
|
||||
$this->configFile = Path::join($this->dataFolder, "config.yml");
|
||||
|
||||
$prefix = $this->getDescription()->getPrefix();
|
||||
$prefix = $this->description->getPrefix();
|
||||
$this->logger = new PluginLogger($server->getLogger(), $prefix !== "" ? $prefix : $this->getName());
|
||||
$this->scheduler = new TaskScheduler($this->getFullName());
|
||||
|
||||
@ -145,9 +145,9 @@ abstract class PluginBase implements Plugin, CommandExecutor{
|
||||
private function registerYamlCommands() : void{
|
||||
$pluginCmds = [];
|
||||
|
||||
foreach(Utils::stringifyKeys($this->getDescription()->getCommands()) as $key => $data){
|
||||
foreach(Utils::stringifyKeys($this->description->getCommands()) as $key => $data){
|
||||
if(str_contains($key, ":")){
|
||||
$this->logger->error($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_plugin_commandError($key, $this->getDescription()->getFullName(), ":")));
|
||||
$this->logger->error($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_plugin_commandError($key, $this->description->getFullName(), ":")));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ abstract class PluginBase implements Plugin, CommandExecutor{
|
||||
$aliasList = [];
|
||||
foreach($data->getAliases() as $alias){
|
||||
if(str_contains($alias, ":")){
|
||||
$this->logger->error($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_plugin_aliasError($alias, $this->getDescription()->getFullName(), ":")));
|
||||
$this->logger->error($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_plugin_aliasError($alias, $this->description->getFullName(), ":")));
|
||||
continue;
|
||||
}
|
||||
$aliasList[] = $alias;
|
||||
@ -181,7 +181,7 @@ abstract class PluginBase implements Plugin, CommandExecutor{
|
||||
}
|
||||
|
||||
if(count($pluginCmds) > 0){
|
||||
$this->server->getCommandMap()->registerAll($this->getDescription()->getName(), $pluginCmds);
|
||||
$this->server->getCommandMap()->registerAll($this->description->getName(), $pluginCmds);
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,9 +190,9 @@ abstract class PluginBase implements Plugin, CommandExecutor{
|
||||
* @phpstan-return (Command&PluginOwned)|null
|
||||
*/
|
||||
public function getCommand(string $name){
|
||||
$command = $this->getServer()->getPluginCommand($name);
|
||||
$command = $this->server->getPluginCommand($name);
|
||||
if($command === null || $command->getOwningPlugin() !== $this){
|
||||
$command = $this->getServer()->getPluginCommand(strtolower($this->description->getName()) . ":" . $name);
|
||||
$command = $this->server->getPluginCommand(strtolower($this->description->getName()) . ":" . $name);
|
||||
}
|
||||
|
||||
if($command instanceof PluginOwned && $command->getOwningPlugin() === $this){
|
||||
|
@ -24,11 +24,10 @@ declare(strict_types=1);
|
||||
namespace pocketmine\scheduler;
|
||||
|
||||
use pmmp\thread\Runnable;
|
||||
use pmmp\thread\Thread as NativeThread;
|
||||
use pmmp\thread\ThreadSafe;
|
||||
use pmmp\thread\ThreadSafeArray;
|
||||
use pocketmine\thread\NonThreadSafeValue;
|
||||
use function assert;
|
||||
use function array_key_exists;
|
||||
use function igbinary_serialize;
|
||||
use function igbinary_unserialize;
|
||||
use function is_null;
|
||||
@ -82,9 +81,7 @@ abstract class AsyncTask extends Runnable{
|
||||
$this->onRun();
|
||||
|
||||
$this->finished = true;
|
||||
$worker = NativeThread::getCurrentThread();
|
||||
assert($worker instanceof AsyncWorker);
|
||||
$worker->getNotifier()->wakeupSleeper();
|
||||
AsyncWorker::getNotifier()->wakeupSleeper();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -230,7 +227,7 @@ abstract class AsyncTask extends Runnable{
|
||||
*/
|
||||
protected function fetchLocal(string $key){
|
||||
$id = spl_object_id($this);
|
||||
if(!isset(self::$threadLocalStorage[$id][$key])){
|
||||
if(!isset(self::$threadLocalStorage[$id]) || !array_key_exists($key, self::$threadLocalStorage[$id])){
|
||||
throw new \InvalidArgumentException("No matching thread-local data found on this thread");
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ class AsyncWorker extends Worker{
|
||||
/** @var mixed[] */
|
||||
private static array $store = [];
|
||||
|
||||
private const TLS_KEY_NOTIFIER = self::class . "::notifier";
|
||||
private static ?SleeperNotifier $notifier = null;
|
||||
|
||||
public function __construct(
|
||||
private ThreadSafeLogger $logger,
|
||||
@ -45,12 +45,11 @@ class AsyncWorker extends Worker{
|
||||
private SleeperHandlerEntry $sleeperEntry
|
||||
){}
|
||||
|
||||
public function getNotifier() : SleeperNotifier{
|
||||
$notifier = $this->getFromThreadStore(self::TLS_KEY_NOTIFIER);
|
||||
if(!$notifier instanceof SleeperNotifier){
|
||||
throw new AssumptionFailedError("SleeperNotifier not found in thread-local storage");
|
||||
public static function getNotifier() : SleeperNotifier{
|
||||
if(self::$notifier !== null){
|
||||
return self::$notifier;
|
||||
}
|
||||
return $notifier;
|
||||
throw new AssumptionFailedError("SleeperNotifier not found in thread-local storage");
|
||||
}
|
||||
|
||||
protected function onRun() : void{
|
||||
@ -66,7 +65,7 @@ class AsyncWorker extends Worker{
|
||||
$this->logger->debug("No memory limit set");
|
||||
}
|
||||
|
||||
$this->saveToThreadStore(self::TLS_KEY_NOTIFIER, $this->sleeperEntry->createNotifier());
|
||||
self::$notifier = $this->sleeperEntry->createNotifier();
|
||||
}
|
||||
|
||||
public function getLogger() : ThreadSafeLogger{
|
||||
@ -84,6 +83,8 @@ class AsyncWorker extends Worker{
|
||||
/**
|
||||
* Saves mixed data into the worker's thread-local object store. This can be used to store objects which you
|
||||
* want to use on this worker thread from multiple AsyncTasks.
|
||||
*
|
||||
* @deprecated Use static class properties instead.
|
||||
*/
|
||||
public function saveToThreadStore(string $identifier, mixed $value) : void{
|
||||
if(NativeThread::getCurrentThread() !== $this){
|
||||
@ -99,6 +100,8 @@ class AsyncWorker extends Worker{
|
||||
* account for the possibility that what you're trying to retrieve might not exist.
|
||||
*
|
||||
* Objects stored in this storage may ONLY be retrieved while the task is running.
|
||||
*
|
||||
* @deprecated Use static class properties instead.
|
||||
*/
|
||||
public function getFromThreadStore(string $identifier) : mixed{
|
||||
if(NativeThread::getCurrentThread() !== $this){
|
||||
@ -109,6 +112,8 @@ class AsyncWorker extends Worker{
|
||||
|
||||
/**
|
||||
* Removes previously-stored mixed data from the worker's thread-local object store.
|
||||
*
|
||||
* @deprecated Use static class properties instead.
|
||||
*/
|
||||
public function removeFromThreadStore(string $identifier) : void{
|
||||
if(NativeThread::getCurrentThread() !== $this){
|
||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\thread;
|
||||
|
||||
use pmmp\thread\Thread as NativeThread;
|
||||
use pmmp\thread\ThreadSafeArray;
|
||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||
use pocketmine\Server;
|
||||
@ -77,9 +78,7 @@ trait CommonThreadPartsTrait{
|
||||
/**
|
||||
* Registers the class loaders for this thread.
|
||||
*
|
||||
* WARNING: This method MUST be called from any descendent threads' run() method to make autoloading usable.
|
||||
* If you do not do this, you will not be able to use new classes that were not loaded when the thread was started
|
||||
* (unless you are using a custom autoloader).
|
||||
* @internal
|
||||
*/
|
||||
public function registerClassLoaders() : void{
|
||||
if($this->composerAutoloaderPath !== null){
|
||||
@ -96,6 +95,15 @@ trait CommonThreadPartsTrait{
|
||||
|
||||
public function getCrashInfo() : ?ThreadCrashInfo{ return $this->crashInfo; }
|
||||
|
||||
public function start(int $options = NativeThread::INHERIT_NONE) : bool{
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if($this->getClassLoaders() === null){
|
||||
$this->setClassLoaders();
|
||||
}
|
||||
return parent::start($options);
|
||||
}
|
||||
|
||||
final public function run() : void{
|
||||
error_reporting(-1);
|
||||
$this->registerClassLoaders();
|
||||
@ -110,6 +118,20 @@ trait CommonThreadPartsTrait{
|
||||
$this->isKilled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
||||
*/
|
||||
public function quit() : void{
|
||||
$this->isKilled = true;
|
||||
|
||||
if(!$this->isJoined()){
|
||||
$this->notify();
|
||||
$this->join();
|
||||
}
|
||||
|
||||
ThreadManager::getInstance()->remove($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by set_exception_handler() when an uncaught exception is thrown.
|
||||
*/
|
||||
|
@ -37,28 +37,4 @@ use pocketmine\scheduler\AsyncTask;
|
||||
*/
|
||||
abstract class Thread extends NativeThread{
|
||||
use CommonThreadPartsTrait;
|
||||
|
||||
public function start(int $options = NativeThread::INHERIT_NONE) : bool{
|
||||
//this is intentionally not traitified
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if($this->getClassLoaders() === null){
|
||||
$this->setClassLoaders();
|
||||
}
|
||||
return parent::start($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
||||
*/
|
||||
public function quit() : void{
|
||||
$this->isKilled = true;
|
||||
|
||||
if(!$this->isJoined()){
|
||||
$this->notify();
|
||||
$this->join();
|
||||
}
|
||||
|
||||
ThreadManager::getInstance()->remove($this);
|
||||
}
|
||||
}
|
||||
|
@ -51,12 +51,12 @@ class ThreadSafeClassLoader extends ThreadSafe{
|
||||
* @var ThreadSafeArray|string[]
|
||||
* @phpstan-var ThreadSafeArray<int, string>
|
||||
*/
|
||||
private $fallbackLookup;
|
||||
private ThreadSafeArray $fallbackLookup;
|
||||
/**
|
||||
* @var ThreadSafeArray|string[][]
|
||||
* @phpstan-var ThreadSafeArray<string, ThreadSafeArray<int, string>>
|
||||
*/
|
||||
private $psr4Lookup;
|
||||
private ThreadSafeArray $psr4Lookup;
|
||||
|
||||
public function __construct(){
|
||||
$this->fallbackLookup = new ThreadSafeArray();
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\thread;
|
||||
|
||||
use pmmp\thread\Thread as NativeThread;
|
||||
use pmmp\thread\Worker as NativeWorker;
|
||||
use pocketmine\scheduler\AsyncTask;
|
||||
|
||||
@ -39,31 +38,4 @@ use pocketmine\scheduler\AsyncTask;
|
||||
*/
|
||||
abstract class Worker extends NativeWorker{
|
||||
use CommonThreadPartsTrait;
|
||||
|
||||
public function start(int $options = NativeThread::INHERIT_NONE) : bool{
|
||||
//this is intentionally not traitified
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
if($this->getClassLoaders() === null){
|
||||
$this->setClassLoaders();
|
||||
}
|
||||
return parent::start($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the thread using the best way possible. Try to stop it yourself before calling this.
|
||||
*/
|
||||
public function quit() : void{
|
||||
$this->isKilled = true;
|
||||
|
||||
if(!$this->isShutdown()){
|
||||
$this->synchronized(function() : void{
|
||||
while($this->unstack() !== null);
|
||||
});
|
||||
$this->notify();
|
||||
$this->shutdown();
|
||||
}
|
||||
|
||||
ThreadManager::getInstance()->remove($this);
|
||||
}
|
||||
}
|
||||
|
@ -213,8 +213,7 @@ abstract class Timings{
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-template T of object
|
||||
* @phpstan-param class-string<T> $class
|
||||
* @phpstan-param class-string<covariant object> $class
|
||||
*/
|
||||
private static function shortenCoreClassName(string $class, string $prefix) : string{
|
||||
if(str_starts_with($class, $prefix)){
|
||||
|
@ -28,7 +28,7 @@ namespace pocketmine\utils;
|
||||
* __callStatic().
|
||||
*
|
||||
* Classes using this trait need to include \@method tags in their class docblock for every enum member.
|
||||
* Alternatively, just put \@generate-registry-docblock in the docblock and run tools/generate-registry-annotations.php
|
||||
* Alternatively, just put \@generate-registry-docblock in the docblock and run build/generate-registry-annotations.php
|
||||
*
|
||||
* @deprecated Use native PHP 8.1 enums instead. Use {@link LegacyEnumShimTrait} if you need to provide backwards
|
||||
* compatible EnumTrait-like API for migrated enums.
|
||||
|
@ -33,7 +33,7 @@ use function preg_match;
|
||||
* These faux constants are exposed in static class methods, which are handled using __callStatic().
|
||||
*
|
||||
* Classes using this trait need to include \@method tags in their class docblock for every faux constant.
|
||||
* Alternatively, just put \@generate-registry-docblock in the docblock and run tools/generate-registry-annotations.php
|
||||
* Alternatively, just put \@generate-registry-docblock in the docblock and run build/generate-registry-annotations.php
|
||||
*/
|
||||
trait RegistryTrait{
|
||||
/**
|
||||
|
@ -24,7 +24,8 @@ declare(strict_types=1);
|
||||
namespace pocketmine\utils;
|
||||
|
||||
use pocketmine\thread\Thread;
|
||||
use function time;
|
||||
use function hrtime;
|
||||
use function intdiv;
|
||||
|
||||
class ServerKiller extends Thread{
|
||||
private bool $stopped = false;
|
||||
@ -34,13 +35,15 @@ class ServerKiller extends Thread{
|
||||
){}
|
||||
|
||||
protected function onRun() : void{
|
||||
$start = time();
|
||||
$this->synchronized(function() : void{
|
||||
if(!$this->stopped){
|
||||
$this->wait($this->time * 1000000);
|
||||
$start = hrtime(true);
|
||||
$remaining = $this->time * 1_000_000;
|
||||
$this->synchronized(function() use (&$remaining, $start) : void{
|
||||
while(!$this->stopped && $remaining > 0){
|
||||
$this->wait($remaining);
|
||||
$remaining -= intdiv(hrtime(true) - $start, 1000);
|
||||
}
|
||||
});
|
||||
if(time() - $start >= $this->time){
|
||||
if($remaining <= 0){
|
||||
echo "\nTook too long to stop, server was killed forcefully!\n";
|
||||
@Process::kill(Process::pid());
|
||||
}
|
||||
|
@ -1016,8 +1016,12 @@ class World implements ChunkManager{
|
||||
continue;
|
||||
}
|
||||
World::getXZ($index, $chunkX, $chunkZ);
|
||||
if(!$this->isChunkLoaded($chunkX, $chunkZ)){
|
||||
//a previous chunk may have caused this one to be unloaded by a ChunkListener
|
||||
continue;
|
||||
}
|
||||
if(count($blocks) > 512){
|
||||
$chunk = $this->getChunk($chunkX, $chunkZ);
|
||||
$chunk = $this->getChunk($chunkX, $chunkZ) ?? throw new AssumptionFailedError("We already checked that the chunk is loaded");
|
||||
foreach($this->getChunkPlayers($chunkX, $chunkZ) as $p){
|
||||
$p->onChunkChanged($chunkX, $chunkZ, $chunk);
|
||||
}
|
||||
@ -2623,7 +2627,7 @@ class World implements ChunkManager{
|
||||
|
||||
public function isChunkPopulated(int $x, int $z) : bool{
|
||||
$chunk = $this->loadChunk($x, $z);
|
||||
return $chunk !== null ? $chunk->isPopulated() : false;
|
||||
return $chunk !== null && $chunk->isPopulated();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,10 +129,6 @@ class WorldManager{
|
||||
}
|
||||
|
||||
$ev = new WorldUnloadEvent($world);
|
||||
if($world === $this->defaultWorld && !$forceUnload){
|
||||
$ev->cancel();
|
||||
}
|
||||
|
||||
$ev->call();
|
||||
|
||||
if(!$forceUnload && $ev->isCancelled()){
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user