mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 03:06:55 +00:00
Compare commits
188 Commits
5.17.1
...
gameplay-p
Author | SHA1 | Date | |
---|---|---|---|
a6042ec7e8 | |||
f1a3b42620 | |||
f3763ae691 | |||
12214792b3 | |||
e494460cfd | |||
2c299e2b49 | |||
ac1e70cd96 | |||
0bbd4af496 | |||
b0bfc30b07 | |||
a91cef37f6 | |||
26afa97cdc | |||
57082c8148 | |||
74ee38ab99 | |||
df069b0418 | |||
ea43fd1917 | |||
93a9007f3c | |||
a593180ef9 | |||
61560ec375 | |||
89f88a9333 | |||
9cab72ed59 | |||
2bd9f4108b | |||
ca5d9c3731 | |||
cbcc4d24e0 | |||
223fd74255 | |||
0fef4c6683 | |||
cd2a1fdc1d | |||
a396233e57 | |||
d666f17ec6 | |||
a84326cb2d | |||
0543bf301e | |||
603ab081bc | |||
daacc8eddb | |||
269effcecf | |||
ae750b60d0 | |||
905a10e980 | |||
52fe2cb97f | |||
8cdc7d7ee1 | |||
12ae8dc03b | |||
a9787f0d99 | |||
5325ecee37 | |||
30ee0aa63d | |||
aef4fa7174 | |||
53aa380ca3 | |||
a5f607138c | |||
8338ebaffd | |||
082119cfd2 | |||
7460e12b6a | |||
a53b0116a0 | |||
5b72f202bf | |||
8b6adf86d6 | |||
0070426e97 | |||
a523ed6e40 | |||
7c2ed7d884 | |||
1e3a858de6 | |||
844ba0ff9f | |||
49bdaee930 | |||
9195c88670 | |||
ae19d05fd5 | |||
bf7a53b00f | |||
e710b3750f | |||
8ccd1edb17 | |||
faf1e26bac | |||
b4259ef988 | |||
b2aa6396c3 | |||
1555fa17e7 | |||
e77f2c5198 | |||
e8e441f739 | |||
48a908ee8c | |||
dc87a2b10e | |||
d3add78d3e | |||
ff695a5f97 | |||
4b630cb726 | |||
4331f69b9c | |||
fb1213e964 | |||
8a693f2a4c | |||
8474eaf5f1 | |||
a75d4687ce | |||
0b0c425805 | |||
b5469dede2 | |||
e0d270a870 | |||
2d9cee3d62 | |||
ed64231c57 | |||
33a7b46329 | |||
9b58d35516 | |||
3629ee7e7b | |||
fbeb017670 | |||
09bf203267 | |||
f3cc4a28e1 | |||
fe70150db2 | |||
054538e6b7 | |||
3586bc42a9 | |||
1f86949836 | |||
053a71c59d | |||
07d5046b83 | |||
4a702b97fd | |||
d2c3b8dacb | |||
fa3529966f | |||
2ff6470792 | |||
05a9e9c76e | |||
231eec911f | |||
8c04d47b1b | |||
b3b8aaddff | |||
2173aab967 | |||
e598364f06 | |||
734ca1cc6b | |||
96b12bddc1 | |||
84464cde4f | |||
72fc138631 | |||
c63d0ef1b6 | |||
82c416624d | |||
9e19391f20 | |||
c0b74b0341 | |||
3c96e72f7d | |||
0376e37966 | |||
94dff74494 | |||
0065fe649f | |||
8ef5e737de | |||
e7d8d99ca6 | |||
414e8acf8c | |||
d372af351a | |||
4814db4fe7 | |||
d01203d7c4 | |||
847f931660 | |||
22718c4971 | |||
acbfb0a3e9 | |||
7f9e79c83e | |||
7e343617b9 | |||
d945cbf517 | |||
c4e72c880e | |||
3ef7001d8e | |||
f1b1a7022d | |||
59d14de1d8 | |||
c8f567b093 | |||
5cc1068cd4 | |||
f6e6f15c63 | |||
4e6b34f573 | |||
a4a07a8e5a | |||
0a7cbdd56d | |||
a5babb2c9f | |||
49c2f13cf0 | |||
60cac18104 | |||
f6e2a1ecce | |||
00e39821f0 | |||
72d941fc1b | |||
8cb2e577a1 | |||
2a7b183ab8 | |||
e9b597af6c | |||
9381fc4172 | |||
281afb6838 | |||
ede363eb0f | |||
bdbcfd10cc | |||
e6f9cdd990 | |||
5241118f0b | |||
93a270d251 | |||
a7638cf914 | |||
c44e6c59fc | |||
92f380bb9c | |||
c32744ebc7 | |||
e3baf3cddb | |||
9176b2494a | |||
0f365886e0 | |||
8c3cf7a687 | |||
994fa5f792 | |||
3ed9615180 | |||
f5ab2979a0 | |||
13f5cc9f87 | |||
1ce774ae73 | |||
e017780cc3 | |||
ee17ac5246 | |||
33dc995cc7 | |||
26761c2b87 | |||
c4a2b6494d | |||
2aa64dc15e | |||
d0d7a995fb | |||
be2437ac6e | |||
bdb5845cec | |||
787afb6b00 | |||
d6c48fd3a2 | |||
ef9791eaed | |||
accaa0acce | |||
2ffc38c835 | |||
f6c0b228ec | |||
b342c497d1 | |||
428e38f913 | |||
5ae13209c0 | |||
371eccd007 | |||
e1ae9a7d69 | |||
10a962daa2 |
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1 @@
|
||||
* @pmmp/server-developers
|
10
.github/ISSUE_TEMPLATE/api-change-request.md
vendored
10
.github/ISSUE_TEMPLATE/api-change-request.md
vendored
@ -7,13 +7,13 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--- tell us what you want -->
|
||||
## Description
|
||||
<!--- Describe the problem you want to solve -->
|
||||
## Problem description
|
||||
|
||||
|
||||
<!--- explain why you want this and why it's a good idea -->
|
||||
## Justification
|
||||
<!--- Describe what changes you want to make to solve this problem -->
|
||||
## Proposed solution
|
||||
|
||||
|
||||
<!--- (optional) describe alternative methods you've explored to achieve your goal -->
|
||||
## Alternative methods
|
||||
## Alternative solutions that don't require API changes
|
||||
|
31
.github/PULL_REQUEST_TEMPLATE.md
vendored
31
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,43 +1,32 @@
|
||||
## Introduction
|
||||
<!-- Summarize your PR here. Keep it short and simple. -->
|
||||
<!-- Explain existing problems or why this pull request is necessary -->
|
||||
|
||||
### Relevant issues
|
||||
<!-- List relevant issues here -->
|
||||
### Related issues & PRs
|
||||
<!--
|
||||
|
||||
* Fixes #1
|
||||
* Fixes #2
|
||||
|
||||
* Related to #2
|
||||
-->
|
||||
|
||||
## Changes
|
||||
### API changes
|
||||
<!-- Any additions to the API that should be documented in release notes? -->
|
||||
<!-- If not, you can delete this section -->
|
||||
|
||||
### Behavioural changes
|
||||
<!-- Any change in how the server behaves, or its performance? -->
|
||||
<!-- If not, you can delete this section -->
|
||||
|
||||
## Backwards compatibility
|
||||
<!-- Any possible backwards incompatible changes? How are they solved, or how can they be solved? -->
|
||||
<!-- If not, you can delete this section -->
|
||||
|
||||
## Follow-up
|
||||
<!-- Suggest any actions to be done before/after merging this pull request -->
|
||||
<!--
|
||||
|
||||
Requires translations:
|
||||
|
||||
| Name | Value in eng.ini |
|
||||
| :--: | :---: |
|
||||
| `foo.bar` | `Foo bar` |
|
||||
|
||||
-->
|
||||
<!-- For example, future changes that this PR lays the groundwork for -->
|
||||
|
||||
## Tests
|
||||
<!--
|
||||
PRs which have not been tested MUST be marked as draft.
|
||||
If this PR affects gameplay or user experience in some way, it must be manually tested.
|
||||
Include any screenshots or videos of manual testing here.
|
||||
Any test plugin code should also be pasted here if it can't be adapted to a PHPUnit test.
|
||||
-->
|
||||
I tested this PR by doing the following (tick all that apply):
|
||||
- [ ] Writing PHPUnit tests (commit these in the `tests/phpunit` folder)
|
||||
- [ ] Playtesting using a Minecraft client (provide screenshots or a video)
|
||||
- [ ] Writing a test plugin (provide the code and sample output)
|
||||
- [ ] Other (provide details)
|
||||
|
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@v6.6.1
|
||||
uses: docker/build-push-action@v6.9.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@v6.6.1
|
||||
uses: docker/build-push-action@v6.9.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@v6.6.1
|
||||
uses: docker/build-push-action@v6.9.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@v6.6.1
|
||||
uses: docker/build-push-action@v6.9.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
|
65
.github/workflows/draft-release-from-pr.yml
vendored
Normal file
65
.github/workflows/draft-release-from-pr.yml
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
name: Draft release from PR
|
||||
|
||||
on:
|
||||
#presume that pull_request_target is safe at this point, since the PR was approved and merged
|
||||
#we need write access to prepare the release & create comments
|
||||
pull_request_target:
|
||||
types:
|
||||
- closed
|
||||
branches:
|
||||
- stable
|
||||
- minor-next
|
||||
- major-next
|
||||
- "legacy/*"
|
||||
paths:
|
||||
- "src/VersionInfo.php"
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check release
|
||||
uses: ./.github/workflows/draft-release-pr-check.yml
|
||||
|
||||
draft:
|
||||
name: Create GitHub draft release
|
||||
needs: [check]
|
||||
if: needs.check.outputs.valid == 'true'
|
||||
|
||||
uses: ./.github/workflows/draft-release.yml
|
||||
|
||||
post-draft-url-comment:
|
||||
name: Post draft release URL as comment
|
||||
needs: [draft]
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Post draft release URL on PR
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
message: "[Draft release ${{ needs.draft.outputs.version }}](${{ needs.draft.outputs.draft-url }}) has been created for commit ${{ github.sha }}. Please review and publish it."
|
||||
|
||||
trigger-post-release-workflow:
|
||||
name: Trigger post-release RestrictedActions workflow
|
||||
# Not sure if needs is actually needed here
|
||||
needs: [check]
|
||||
if: needs.check.outputs.valid == 'true'
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Generate access token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@v1
|
||||
with:
|
||||
app-id: ${{ vars.RESTRICTED_ACTIONS_DISPATCH_ID }}
|
||||
private-key: ${{ secrets.RESTRICTED_ACTIONS_DISPATCH_KEY }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
repositories: RestrictedActions
|
||||
|
||||
- name: Dispatch post-release restricted action
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
repository: ${{ github.repository_owner }}/RestrictedActions
|
||||
event-type: pocketmine_mp_post_release
|
||||
client-payload: '{"branch": "${{ github.ref }}"}'
|
13
.github/workflows/draft-release-from-tag.yml
vendored
Normal file
13
.github/workflows/draft-release-from-tag.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
#Allows creating a release by pushing a tag
|
||||
#This might be useful for retroactive releases
|
||||
name: Draft release from git tag
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: "*"
|
||||
|
||||
jobs:
|
||||
draft:
|
||||
name: Create GitHub draft release
|
||||
if: "startsWith(github.event.head_commit.message, 'Release ')"
|
||||
uses: ./.github/workflows/draft-release.yml
|
111
.github/workflows/draft-release-pr-check.yml
vendored
Normal file
111
.github/workflows/draft-release-pr-check.yml
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
name: Release PR checks
|
||||
|
||||
on:
|
||||
#do checks on every PR update
|
||||
pull_request:
|
||||
branches:
|
||||
- stable
|
||||
- minor-next
|
||||
- major-next
|
||||
- "legacy/*"
|
||||
paths:
|
||||
- "src/VersionInfo.php"
|
||||
|
||||
#allow this workflow to be invoked on PR merge, prior to creating the release
|
||||
workflow_call:
|
||||
outputs:
|
||||
valid:
|
||||
description: Whether this commit is valid for release
|
||||
value: ${{ jobs.check-intent.outputs.valid && jobs.check-validity.result == 'success' }}
|
||||
|
||||
permissions:
|
||||
contents: read #for user access check
|
||||
|
||||
jobs:
|
||||
check-intent:
|
||||
name: Check release trigger
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
outputs:
|
||||
valid: ${{ steps.validate.outputs.DEV_BUILD == 'false' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Check IS_DEVELOPMENT_BUILD flag
|
||||
id: validate
|
||||
run: |
|
||||
echo DEV_BUILD=$(sed -n "s/^\s*public const IS_DEVELOPMENT_BUILD = \(true\|false\);$/\1/p" src/VersionInfo.php) >> $GITHUB_OUTPUT
|
||||
|
||||
check-validity:
|
||||
name: Validate release info
|
||||
needs: [check-intent]
|
||||
#don't do these checks if this isn't a release - we don't want to generate unnecessary failed statuses
|
||||
if: needs.check-intent.outputs.valid == 'true'
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@2.31.1
|
||||
with:
|
||||
php-version: 8.2
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/composer/files
|
||||
~/.cache/composer/vcs
|
||||
key: "composer-v2-cache-${{ hashFiles('./composer.lock') }}"
|
||||
restore-keys: |
|
||||
composer-v2-cache-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-dev --prefer-dist --no-interaction --ignore-platform-reqs
|
||||
|
||||
- name: Check author permissions
|
||||
id: check-permission
|
||||
uses: actions-cool/check-user-permission@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
require: write
|
||||
username: ${{ github.event.pull_request.user.login }}
|
||||
#technically this would be fine for dependabot but generally bots don't count as team members
|
||||
check-bot: true
|
||||
|
||||
- name: Abort if user permissions are insufficient
|
||||
#user doesn't have permission or is a bot
|
||||
if: steps.check-permission.outputs.require-result != 'true' || steps.check-permission.outputs.check-result != 'false'
|
||||
run: |
|
||||
echo "::error::This user is not authorized to trigger releases"
|
||||
exit 1
|
||||
|
||||
- name: Check changelog file is present
|
||||
id: file-presence
|
||||
run: |
|
||||
CHANGELOG_FILE="changelogs/$(php build/dump-version-info.php changelog_file_name)"
|
||||
if [ ! -f "${{ github.workspace }}/$CHANGELOG_FILE" ]; then
|
||||
echo "::error::$CHANGELOG_FILE does not exist"
|
||||
exit 1
|
||||
fi
|
||||
echo FILE="$CHANGELOG_FILE" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check header is present in changelog file
|
||||
run: |
|
||||
FILE="${{ steps.file-presence.outputs.FILE }}"
|
||||
VERSION="$(php build/dump-version-info.php base_version)"
|
||||
if ! grep -Fqx "# $VERSION" "${{ github.workspace }}/$FILE"; then
|
||||
echo "::error::Header for $VERSION not found in $FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check version is valid for the selected channel
|
||||
run: |
|
||||
CHANNEL="$(php build/dump-version-info.php channel)"
|
||||
if [ "$(php build/dump-version-info.php suffix_valid)" != "true" ]; then
|
||||
echo "::error::Version $(php build/dump-version-info.php base_version) is not allowed on the $CHANNEL channel"
|
||||
exit 1
|
||||
fi
|
34
.github/workflows/draft-release.yml
vendored
34
.github/workflows/draft-release.yml
vendored
@ -1,19 +1,29 @@
|
||||
name: Draft release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: "*"
|
||||
workflow_call:
|
||||
outputs:
|
||||
draft-url:
|
||||
description: 'The URL of the draft release'
|
||||
value: ${{ jobs.draft.outputs.draft-url }}
|
||||
version:
|
||||
description: 'PocketMine-MP version'
|
||||
value: ${{ jobs.draft.outputs.version }}
|
||||
|
||||
jobs:
|
||||
draft:
|
||||
name: Create GitHub draft release
|
||||
if: "startsWith(github.event.head_commit.message, 'Release ')"
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-version: [8.2]
|
||||
|
||||
outputs:
|
||||
draft-url: ${{ steps.create-draft.outputs.html_url }}
|
||||
version: ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@ -53,17 +63,17 @@ jobs:
|
||||
- name: Get PocketMine-MP release version
|
||||
id: get-pm-version
|
||||
run: |
|
||||
echo PM_VERSION=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BASE_VERSION;') >> $GITHUB_OUTPUT
|
||||
echo MCPE_VERSION=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK;') >> $GITHUB_OUTPUT
|
||||
echo PM_VERSION_SHORT=$(php -r 'require "vendor/autoload.php"; $v = explode(".", \pocketmine\VersionInfo::BASE_VERSION); array_pop($v); echo implode(".", $v);') >> $GITHUB_OUTPUT
|
||||
echo PM_VERSION_MD=$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);') >> $GITHUB_OUTPUT
|
||||
echo CHANGELOG_SUFFIX=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "" : "-" . \pocketmine\VersionInfo::BUILD_CHANNEL;') >> $GITHUB_OUTPUT
|
||||
echo PRERELEASE=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "false" : "true";') >> $GITHUB_OUTPUT
|
||||
echo PM_VERSION=$(php build/dump-version-info.php base_version) >> $GITHUB_OUTPUT
|
||||
echo PM_MAJOR=$(php build/dump-version-info.php major_version) >> $GITHUB_OUTPUT
|
||||
echo MCPE_VERSION=$(php build/dump-version-info.php mcpe_version) >> $GITHUB_OUTPUT
|
||||
echo CHANGELOG_FILE_NAME=$(php build/dump-version-info.php changelog_file_name) >> $GITHUB_OUTPUT
|
||||
echo CHANGELOG_MD_HEADER=$(php build/dump-version-info.php changelog_md_header) >> $GITHUB_OUTPUT
|
||||
echo PRERELEASE=$(php build/dump-version-info.php prerelease) >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Generate PHP binary download URL
|
||||
id: php-binary-url
|
||||
run: |
|
||||
echo PHP_BINARY_URL="${{ github.server_url }}/${{ github.repository_owner }}/PHP-Binaries/releases/tag/php-${{ matrix.php-version }}-latest" >> $GITHUB_OUTPUT
|
||||
echo PHP_BINARY_URL="${{ github.server_url }}/${{ github.repository_owner }}/PHP-Binaries/releases/tag/pm${{ steps.get-pm-version.outputs.PM_MAJOR }}-php-${{ matrix.php-version }}-latest" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Generate build info
|
||||
run: |
|
||||
@ -91,6 +101,7 @@ jobs:
|
||||
|
||||
- name: Create draft release
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
id: create-draft
|
||||
with:
|
||||
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json,${{ github.workspace }}/core-permissions.rst
|
||||
commit: ${{ github.sha }}
|
||||
@ -99,9 +110,10 @@ jobs:
|
||||
name: PocketMine-MP ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
||||
tag: ${{ steps.get-pm-version.outputs.PM_VERSION }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
skipIfReleaseExists: true #for release PRs, tags will be created on release publish and trigger the tag release workflow - don't create a second draft
|
||||
body: |
|
||||
**For Minecraft: Bedrock Edition ${{ steps.get-pm-version.outputs.MCPE_VERSION }}**
|
||||
|
||||
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}${{ steps.get-pm-version.outputs.CHANGELOG_SUFFIX }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
|
||||
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.CHANGELOG_FILE_NAME }}#${{ steps.get-pm-version.outputs.CHANGELOG_MD_HEADER }}) for details.
|
||||
|
||||
:information_source: Download the recommended PHP binary [here](${{ steps.php-binary-url.outputs.PHP_BINARY_URL }}).
|
||||
|
8
.github/workflows/main-php-matrix.yml
vendored
8
.github/workflows/main-php-matrix.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@3.1.0
|
||||
uses: pmmp/setup-php-action@3.2.0
|
||||
with:
|
||||
php-version: ${{ inputs.php }}
|
||||
install-path: "./bin"
|
||||
@ -62,7 +62,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@3.1.0
|
||||
uses: pmmp/setup-php-action@3.2.0
|
||||
with:
|
||||
php-version: ${{ inputs.php }}
|
||||
install-path: "./bin"
|
||||
@ -96,7 +96,7 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@3.1.0
|
||||
uses: pmmp/setup-php-action@3.2.0
|
||||
with:
|
||||
php-version: ${{ inputs.php }}
|
||||
install-path: "./bin"
|
||||
@ -128,7 +128,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@3.1.0
|
||||
uses: pmmp/setup-php-action@3.2.0
|
||||
with:
|
||||
php-version: ${{ inputs.php }}
|
||||
install-path: "./bin"
|
||||
|
12
.github/workflows/main.yml
vendored
12
.github/workflows/main.yml
vendored
@ -37,3 +37,15 @@ jobs:
|
||||
|
||||
- name: Run PHP-CS-Fixer
|
||||
run: php-cs-fixer fix --dry-run --diff --ansi
|
||||
|
||||
shellcheck:
|
||||
name: ShellCheck
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run ShellCheck
|
||||
uses: ludeeus/action-shellcheck@2.0.0
|
||||
|
33
.github/workflows/pr-remove-waiting-label.yml
vendored
Normal file
33
.github/workflows/pr-remove-waiting-label.yml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
name: Remove waiting label from PRs
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: synchronize
|
||||
|
||||
jobs:
|
||||
delabel:
|
||||
name: Remove label
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Remove label
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
script: |
|
||||
const [owner, repo] = context.payload.repository.full_name.split('/');
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: context.payload.number,
|
||||
name: "Status: Waiting on Author",
|
||||
});
|
||||
} catch (error) {
|
||||
if (error.status === 404) {
|
||||
//probably label wasn't set on the issue
|
||||
console.log('Failed to remove label (probably label isn\'t on the PR): ' + error.message);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
38
.github/workflows/team-pr-auto-approve.yml
vendored
Normal file
38
.github/workflows/team-pr-auto-approve.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
#Due to GitHub awkwardness, it's not easy to reduce the review requirement for collaborators.
|
||||
#Our policy is that 2 collaborators should be aware of every change.
|
||||
#For outside PRs, this means 2 collaborator reviews.
|
||||
#For PRs made by collaborators, this means 1 reviewer + the author.
|
||||
#We trust that collaborators don't need as much oversight.
|
||||
name: Auto approve collaborator PRs
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- ready_for_review
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
dispatch:
|
||||
name: Request approval
|
||||
runs-on: ubuntu-latest
|
||||
if: '! github.event.pull_request.draft'
|
||||
|
||||
steps:
|
||||
- name: Generate access token
|
||||
id: generate-token
|
||||
uses: actions/create-github-app-token@v1
|
||||
with:
|
||||
app-id: ${{ vars.RESTRICTED_ACTIONS_DISPATCH_ID }}
|
||||
private-key: ${{ secrets.RESTRICTED_ACTIONS_DISPATCH_KEY }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
repositories: RestrictedActions
|
||||
|
||||
- name: Dispatch restricted action
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
repository: ${{ github.repository_owner }}/RestrictedActions
|
||||
event-type: auto_approve_collaborator_pr
|
||||
client-payload: '{"repo": "${{ github.repository }}", "pull_request_id": "${{ github.event.pull_request.number }}", "reviewer_id": "0" }'
|
87
build/dump-version-info.php
Normal file
87
build/dump-version-info.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?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);
|
||||
|
||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||
use pocketmine\VersionInfo;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
/*
|
||||
* Dumps version info in a machine-readable format for use in GitHub Actions workflows
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var string[]|\Closure[] $options
|
||||
* @phpstan-var array<string, string|\Closure() : string> $options
|
||||
*/
|
||||
$options = [
|
||||
"base_version" => VersionInfo::BASE_VERSION,
|
||||
"major_version" => fn() => explode(".", VersionInfo::BASE_VERSION)[0],
|
||||
"mcpe_version" => ProtocolInfo::MINECRAFT_VERSION_NETWORK,
|
||||
"is_dev" => VersionInfo::IS_DEVELOPMENT_BUILD,
|
||||
"changelog_file_name" => function() : string{
|
||||
$version = VersionInfo::VERSION();
|
||||
$result = $version->getMajor() . "." . $version->getMinor();
|
||||
$suffix = $version->getSuffix();
|
||||
if($suffix !== ""){
|
||||
if(preg_match('/^([A-Za-z]+)(\d+)$/', $suffix, $matches) !== 1){
|
||||
fwrite(STDERR, "error: invalid current version suffix \"$suffix\"; aborting" . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
$baseSuffix = $matches[1];
|
||||
$result .= "-" . strtolower($baseSuffix);
|
||||
}
|
||||
return $result . ".md";
|
||||
},
|
||||
"changelog_md_header" => fn() : string => str_replace(".", "", VersionInfo::BASE_VERSION),
|
||||
"prerelease" => fn() : bool => VersionInfo::VERSION()->getSuffix() !== "",
|
||||
"channel" => VersionInfo::BUILD_CHANNEL,
|
||||
"suffix_valid" => function() : bool{
|
||||
//TODO: maybe this should be put into its own script?
|
||||
$suffix = VersionInfo::VERSION()->getSuffix();
|
||||
if(VersionInfo::BUILD_CHANNEL === "stable"){
|
||||
//stable builds may not have suffixes
|
||||
return $suffix === "";
|
||||
}
|
||||
if(VersionInfo::BUILD_CHANNEL === "alpha" || VersionInfo::BUILD_CHANNEL === "beta"){
|
||||
$upperChannel = strtoupper(VersionInfo::BUILD_CHANNEL);
|
||||
$upperSuffix = strtoupper($suffix);
|
||||
return str_starts_with($upperSuffix, $upperChannel) && is_numeric(substr($upperSuffix, strlen($upperChannel)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
];
|
||||
if(count($argv) !== 2 || !isset($options[$argv[1]])){
|
||||
fwrite(STDERR, "Please provide an option (one of: " . implode(", ", array_keys($options)) . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$result = $options[$argv[1]];
|
||||
if($result instanceof Closure){
|
||||
$result = $result();
|
||||
}
|
||||
if(is_bool($result)){
|
||||
echo $result ? "true" : "false";
|
||||
}else{
|
||||
echo $result;
|
||||
}
|
@ -122,7 +122,7 @@ if(!is_array($ids)){
|
||||
throw new \RuntimeException("Invalid biome ID map, expected array for root JSON object");
|
||||
}
|
||||
$cleanedIds = [];
|
||||
foreach($ids as $name => $id){
|
||||
foreach(Utils::promoteKeys($ids) as $name => $id){
|
||||
if(!is_string($name) || !is_int($id)){
|
||||
throw new \RuntimeException("Invalid biome ID map, expected string => int map");
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ $constants = [];
|
||||
* @phpstan-param-out array<string, string> $constants
|
||||
*/
|
||||
function collectProperties(string $prefix, array $properties, array &$constants) : void{
|
||||
foreach($properties as $propertyName => $property){
|
||||
foreach(Utils::promoteKeys($properties) as $propertyName => $property){
|
||||
$fullPropertyName = ($prefix !== "" ? $prefix . "." : "") . $propertyName;
|
||||
|
||||
$constName = str_replace([".", "-"], "_", strtoupper($fullPropertyName));
|
||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\build\update_registry_annotations;
|
||||
|
||||
use pocketmine\utils\Utils;
|
||||
use function basename;
|
||||
use function class_exists;
|
||||
use function count;
|
||||
@ -48,6 +49,7 @@ if(count($argv) !== 2){
|
||||
|
||||
/**
|
||||
* @param object[] $members
|
||||
* @phpstan-param array<string, object> $members
|
||||
*/
|
||||
function generateMethodAnnotations(string $namespaceName, array $members) : string{
|
||||
$selfName = basename(__FILE__);
|
||||
@ -60,7 +62,7 @@ function generateMethodAnnotations(string $namespaceName, array $members) : stri
|
||||
|
||||
static $lineTmpl = " * @method static %2\$s %s()";
|
||||
$memberLines = [];
|
||||
foreach($members as $name => $member){
|
||||
foreach(Utils::stringifyKeys($members) as $name => $member){
|
||||
$reflect = new \ReflectionClass($member);
|
||||
while($reflect !== false && $reflect->isAnonymous()){
|
||||
$reflect = $reflect->getParentClass();
|
||||
|
@ -86,7 +86,8 @@ function systemWrapper(string $command, string $errorMessage) : void{
|
||||
|
||||
function main() : void{
|
||||
$filteredOpts = [];
|
||||
foreach(Utils::stringifyKeys(getopt("", ["current:", "next:", "channel:", "help"])) as $optName => $optValue){
|
||||
$postCommitOnly = false;
|
||||
foreach(Utils::stringifyKeys(getopt("", ["current:", "next:", "channel:", "help", "post"])) as $optName => $optValue){
|
||||
if($optName === "help"){
|
||||
fwrite(STDOUT, "Options:\n");
|
||||
|
||||
@ -96,6 +97,10 @@ function main() : void{
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
if($optName === "post"){
|
||||
$postCommitOnly = true;
|
||||
continue;
|
||||
}
|
||||
if(!is_string($optValue)){
|
||||
fwrite(STDERR, "--$optName expects exactly 1 value\n");
|
||||
exit(1);
|
||||
@ -141,20 +146,25 @@ function main() : void{
|
||||
$channel ??= "stable";
|
||||
}
|
||||
|
||||
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
|
||||
echo "$currentVer will be published on release channel \"$channel\".\n";
|
||||
echo "please add appropriate notes to the changelog and press enter...";
|
||||
fgets(STDIN);
|
||||
systemWrapper('git add "' . dirname(__DIR__) . '/changelogs"', "failed to stage changelog changes");
|
||||
system('git diff --cached --quiet "' . dirname(__DIR__) . '/changelogs"', $result);
|
||||
if($result === 0){
|
||||
echo "error: no changelog changes detected; aborting\n";
|
||||
exit(1);
|
||||
}
|
||||
$versionInfoPath = dirname(__DIR__) . '/src/VersionInfo.php';
|
||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false, $channel);
|
||||
systemWrapper('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"', "failed to create release commit");
|
||||
systemWrapper('git tag ' . $currentVer->getBaseVersion(), "failed to create release tag");
|
||||
|
||||
if($postCommitOnly){
|
||||
echo "Skipping release commit & tag. Bumping to next version $nextVer directly.\n";
|
||||
}else{
|
||||
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
|
||||
echo "$currentVer will be published on release channel \"$channel\".\n";
|
||||
echo "please add appropriate notes to the changelog and press enter...";
|
||||
fgets(STDIN);
|
||||
systemWrapper('git add "' . dirname(__DIR__) . '/changelogs"', "failed to stage changelog changes");
|
||||
system('git diff --cached --quiet "' . dirname(__DIR__) . '/changelogs"', $result);
|
||||
if($result === 0){
|
||||
echo "error: no changelog changes detected; aborting\n";
|
||||
exit(1);
|
||||
}
|
||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false, $channel);
|
||||
systemWrapper('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"', "failed to create release commit");
|
||||
systemWrapper('git tag ' . $currentVer->getBaseVersion(), "failed to create release tag");
|
||||
}
|
||||
|
||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true, $channel);
|
||||
systemWrapper('git add "' . $versionInfoPath . '"', "failed to stage changes for post-release commit");
|
||||
|
Submodule build/php updated: 084822aa9e...5016e0a3d5
30
changelogs/5.18.md
Normal file
30
changelogs/5.18.md
Normal file
@ -0,0 +1,30 @@
|
||||
# 5.18.0
|
||||
Released 16th August 2024.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.21.20**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.21.20.
|
||||
|
||||
**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.21.20.
|
||||
- Removed support for earlier versions.
|
||||
|
||||
## Fixes
|
||||
- Use `VISIBLE_MOB_EFFECTS` actor metadata property to send effect bubbles, this fixes effect bubbles not showing
|
||||
|
||||
# 5.18.1
|
||||
Released 3rd September 2024.
|
||||
|
||||
## Fixes
|
||||
- Fixed shift-crafting.
|
||||
- Blue Ice block no longer emits light & it's now dropped when mined with a tool with silk touch enchantment.
|
||||
|
||||
## Internals
|
||||
- Pull Requests from team members now get an approval automatically. This means that if a team member makes a PR, only one other approval should be needed.
|
||||
- Added [ShellCheck](https://github.com/koalaman/shellcheck) to the CI tests.
|
16
changelogs/5.19.md
Normal file
16
changelogs/5.19.md
Normal file
@ -0,0 +1,16 @@
|
||||
# 5.19.0
|
||||
Released 21st September 2024.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.21.30**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.21.30.
|
||||
|
||||
**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.21.30.
|
||||
- Removed support for earlier versions.
|
25
changelogs/5.20.md
Normal file
25
changelogs/5.20.md
Normal file
@ -0,0 +1,25 @@
|
||||
# 5.20.0
|
||||
Released 26th October 2024.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.21.40**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.21.40.
|
||||
|
||||
**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.21.40.
|
||||
- Removed support for earlier versions.
|
||||
|
||||
## Fixes
|
||||
- Fixed a bug in `tools/generate-blockstate-upgrade-schema.php` that caused it to fail on 1.21.40 with the new mushroom block changes.
|
||||
|
||||
# 5.20.1
|
||||
Released 31st October 2024.
|
||||
|
||||
## Fixes
|
||||
- Workaround old mob heads in world saves not being upgraded correctly and causing crashes.
|
128
changelogs/5.21.md
Normal file
128
changelogs/5.21.md
Normal file
@ -0,0 +1,128 @@
|
||||
# 5.21.0
|
||||
Released 3rd November 2024.
|
||||
|
||||
This is a minor feature release, including gameplay features and minor internals 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.
|
||||
|
||||
## Gameplay
|
||||
- Added the following new blocks:
|
||||
- Campfire
|
||||
- Chiseled Copper
|
||||
- Chiseled Tuff
|
||||
- Chiseled Tuff Bricks
|
||||
- Copper Bulb
|
||||
- Copper Door
|
||||
- Copper Grate
|
||||
- Copper Trapdoor
|
||||
- Polished Tuff, Slabs, Stairs and Walls
|
||||
- Soul Campfire
|
||||
- Tuff Bricks, Slabs, Stairs and Walls
|
||||
- Tuff Slab, Stairs and Walls
|
||||
- Added the following new types of painting:
|
||||
- backyard
|
||||
- baroque
|
||||
- bouquet
|
||||
- cavebird
|
||||
- changing
|
||||
- cotan
|
||||
- endboss
|
||||
- fern
|
||||
- finding
|
||||
- humble
|
||||
- lowmist
|
||||
- meditative
|
||||
- orb
|
||||
- owlemons
|
||||
- passage
|
||||
- pond
|
||||
- prairie_ride
|
||||
- sunflowers
|
||||
- tides
|
||||
- unpacked
|
||||
- Armor slots are now properly restricted (on the server side) to only contain the appropriate type of armor or headwear.
|
||||
- Implemented Aqua Affinity enchantment. Since the server doesn't currently enforce any movement restrictions in water, this enchantment works based on client-side behaviour only.
|
||||
|
||||
## API
|
||||
### `pocketmine\block`
|
||||
- The following new API methods have been added:
|
||||
- `public ChiseledBookshelf->getLastInteractedSlot() : ?ChiseledBookshelfSlot`
|
||||
- `public ChiseledBookshelf->setLastInteractedSlot(?ChiseledBookshelfSlot $lastInteractedSlot) : $this`
|
||||
- The following new classes have been added:
|
||||
- `utils\CopperMaterial` - interface implemented by all copper-like blocks with oxidation and waxed properties
|
||||
- `CopperBulb`
|
||||
- `CopperDoor`
|
||||
- `CopperGrate`
|
||||
- `CopperTrapdoor`
|
||||
- `SoulCampfire`
|
||||
- `Campfire`
|
||||
- The following enums have new cases:
|
||||
- `utils\BannerPatternType` has new cases `FLOW` and `GUSTER`
|
||||
|
||||
### `pocketmine\crafting`
|
||||
- The following enums have new cases:
|
||||
- `FurnaceType` has new cases `CAMPFIRE` and `SOUL_CAMPFIRE`
|
||||
|
||||
### `pocketmine\event`
|
||||
- The following new classes have been added:
|
||||
- `block\CampfireCookEvent` - called when a campfire finishes cooking an item
|
||||
|
||||
### `pocketmine\inventory`
|
||||
- Added support for slot validators, which permit restricting the types of items a player can put into an inventory slot.
|
||||
- The following new classes have been added:
|
||||
- `transaction\action\SlotValidator` - interface
|
||||
- `transaction\action\CallbackSlotValidator` - class allowing a closure to be used for slot content validation
|
||||
- `SlotValidatedInventory` - implemented by inventories which support the use of slot validators
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following new API methods have been added:
|
||||
- `public Item->getCooldownTag() : ?string` - returns the cooldown group this item belongs to, used for ensuring that, for example, different types of goat horns all respect a general horn cooldown
|
||||
- The following new classes have been added:
|
||||
- `ItemCooldownTags` - list of cooldown group tags used by PocketMine-MP
|
||||
|
||||
### `pocketmine\world\sound`
|
||||
- The following new classes have been added
|
||||
- `CampfireSound` - sound made by campfires while lit
|
||||
|
||||
## Tools
|
||||
- `tools/blockstate-upgrade-schema-utils.php` (formerly `generate-blockstate-upgrade-schema.php`) has several improvements:
|
||||
- Support for generating `flattenedProperties` rules as per [BedrockBlockUpgradeSchema 5.0.0](https://github.com/pmmp/BedrockBlockUpgradeSchema/releases/tag/5.0.0)
|
||||
- Improved criteria for flattened property selection to minimize the amount of rules required
|
||||
- Several subcommands are now available:
|
||||
- `generate` - generates a schema from provided data
|
||||
- `update` - regenerates an existing schema in a newer format
|
||||
- `update-all` - regenerates a folder of existing schemas in a newer format (useful for updating `BedrockBlockUpgradeSchema` en masse)
|
||||
- `test` - verifies that a schema produces the results expected by provided data
|
||||
|
||||
## Internals
|
||||
- Fixed incorrect visibility of `createEntity` in spawn eggs.
|
||||
- Added support for newer `BedrockBlockUpgradeSchema` in `BlockStateUpgrader`.
|
||||
|
||||
# 5.21.1
|
||||
Released 12th November 2024.
|
||||
|
||||
## Fixes
|
||||
- Fixed server crash when applying a cooldown to an item with 1 count.
|
||||
- Fixed garbage collector cycle count increase on player disconnect.
|
||||
- Fixed weakness effect being applied to all attack types, causing damage splash potions to become weaker.
|
||||
- Fixed Enchanted Golden Apple regeneration effect amplifier to match vanilla.
|
||||
|
||||
# 5.21.2
|
||||
Released 29th November 2024.
|
||||
|
||||
## Fixes
|
||||
- Fixed blocks destroyable by water being able to be placed inside water.
|
||||
- Fixed deprecation warnings about nullable typehints on PHP 8.4.
|
||||
- Fixed `Utils::getNiceClosureName()` not working correctly on PHP 8.4.
|
||||
- Fixed incorrect break animations when breaking the block behind an instantly-breakable block like a torch.
|
||||
- Fixed candle extinguish logic.
|
||||
- Fixed various documentation issues around array key types.
|
||||
- Introduced a new PHPStan rule along with `Utils::promoteKeys()` to improve PHPStan error reporting around unspecified array key types. Previously, some errors were missed due to PHPStan's BenevolentUnionType.
|
||||
|
||||
## DevOps
|
||||
- `pmmp/server-developers` team is now automatically requested for review on any new PR.
|
||||
- `Status: Waiting on Author` label is now automatically removed from PRs when they are updated.
|
@ -33,15 +33,15 @@
|
||||
"composer-runtime-api": "^2.0",
|
||||
"adhocore/json-comment": "~1.2.0",
|
||||
"pocketmine/netresearch-jsonmapper": "~v4.4.999",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~4.2.0+bedrock-1.21.0",
|
||||
"pocketmine/bedrock-data": "~2.11.0+bedrock-1.21.0",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "~1.10.0+bedrock-1.21.0",
|
||||
"pocketmine/bedrock-protocol": "~32.1.0+bedrock-1.21.2",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~5.0.0+bedrock-1.21.40",
|
||||
"pocketmine/bedrock-data": "~2.14.0+bedrock-1.21.40",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "~1.13.0+bedrock-1.21.40",
|
||||
"pocketmine/bedrock-protocol": "~35.0.0+bedrock-1.21.40",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/color": "^0.3.0",
|
||||
"pocketmine/errorhandler": "^0.7.0",
|
||||
"pocketmine/locale-data": "~2.19.0",
|
||||
"pocketmine/locale-data": "~2.22.0",
|
||||
"pocketmine/log": "^0.4.0",
|
||||
"pocketmine/math": "~1.0.0",
|
||||
"pocketmine/nbt": "~1.0.0",
|
||||
@ -52,7 +52,7 @@
|
||||
"symfony/filesystem": "~6.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.11.10",
|
||||
"phpstan/phpstan": "1.11.11",
|
||||
"phpstan/phpstan-phpunit": "^1.1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.2.0",
|
||||
"phpunit/phpunit": "^10.5.24"
|
||||
|
236
composer.lock
generated
236
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": "38063b4fcc2e80a5bccb8d5cc8623cf8",
|
||||
"content-hash": "c57e8f52250edfd03906219fe14fc240",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -127,16 +127,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-block-upgrade-schema",
|
||||
"version": "4.2.0",
|
||||
"version": "5.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git",
|
||||
"reference": "8a327197b3b462fa282f40f76b070ffe585a25d2"
|
||||
"reference": "20dd5c11e9915bacea4fe2cf649e1d23697a6e52"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/8a327197b3b462fa282f40f76b070ffe585a25d2",
|
||||
"reference": "8a327197b3b462fa282f40f76b070ffe585a25d2",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/20dd5c11e9915bacea4fe2cf649e1d23697a6e52",
|
||||
"reference": "20dd5c11e9915bacea4fe2cf649e1d23697a6e52",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -147,22 +147,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/4.2.0"
|
||||
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/5.0.0"
|
||||
},
|
||||
"time": "2024-06-13T17:28:26+00:00"
|
||||
"time": "2024-11-03T14:13:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-data",
|
||||
"version": "2.11.0+bedrock-1.21.0",
|
||||
"version": "2.14.1+bedrock-1.21.40",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockData.git",
|
||||
"reference": "cae40bde98081b388c4d3ab59d45b8d1cf5d8761"
|
||||
"reference": "4a41864ed09613ecec6791e2ae076a8ec7089cc4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/cae40bde98081b388c4d3ab59d45b8d1cf5d8761",
|
||||
"reference": "cae40bde98081b388c4d3ab59d45b8d1cf5d8761",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/4a41864ed09613ecec6791e2ae076a8ec7089cc4",
|
||||
"reference": "4a41864ed09613ecec6791e2ae076a8ec7089cc4",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -173,22 +173,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.21.0"
|
||||
"source": "https://github.com/pmmp/BedrockData/tree/2.14.1+bedrock-1.21.40"
|
||||
},
|
||||
"time": "2024-06-13T17:17:55+00:00"
|
||||
"time": "2024-11-12T21:36:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-item-upgrade-schema",
|
||||
"version": "1.10.0",
|
||||
"version": "1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git",
|
||||
"reference": "b4687afa19f91eacebd46c40d487f4cc515be504"
|
||||
"reference": "1cf81305f2ffcf7dde9577c4f16a55c765192b03"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/b4687afa19f91eacebd46c40d487f4cc515be504",
|
||||
"reference": "b4687afa19f91eacebd46c40d487f4cc515be504",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/1cf81305f2ffcf7dde9577c4f16a55c765192b03",
|
||||
"reference": "1cf81305f2ffcf7dde9577c4f16a55c765192b03",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -199,22 +199,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.10.0"
|
||||
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.13.1"
|
||||
},
|
||||
"time": "2024-05-15T15:15:55+00:00"
|
||||
"time": "2024-11-12T21:33:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-protocol",
|
||||
"version": "32.1.0+bedrock-1.21.2",
|
||||
"version": "35.0.0+bedrock-1.21.40",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockProtocol.git",
|
||||
"reference": "bb23db51365bdc91d3135c3885986a691ae1cb44"
|
||||
"reference": "6aa7cbeb4a7ec6fa58f9024aeaddad7c5c65a459"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/bb23db51365bdc91d3135c3885986a691ae1cb44",
|
||||
"reference": "bb23db51365bdc91d3135c3885986a691ae1cb44",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/6aa7cbeb4a7ec6fa58f9024aeaddad7c5c65a459",
|
||||
"reference": "6aa7cbeb4a7ec6fa58f9024aeaddad7c5c65a459",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -227,7 +227,7 @@
|
||||
"ramsey/uuid": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.11.2",
|
||||
"phpstan/phpstan": "1.11.9",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0.0",
|
||||
"phpunit/phpunit": "^9.5 || ^10.0"
|
||||
@ -245,9 +245,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/32.1.0+bedrock-1.21.2"
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/35.0.0+bedrock-1.21.40"
|
||||
},
|
||||
"time": "2024-07-10T01:38:43+00:00"
|
||||
"time": "2024-10-24T15:45:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
@ -420,16 +420,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/locale-data",
|
||||
"version": "2.19.6",
|
||||
"version": "2.22.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Language.git",
|
||||
"reference": "93e473e20e7f4515ecf45c5ef0f9155b9247a86e"
|
||||
"reference": "aed64e9ca92ffbb20788b3b3bb75b60e4f0eae2d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Language/zipball/93e473e20e7f4515ecf45c5ef0f9155b9247a86e",
|
||||
"reference": "93e473e20e7f4515ecf45c5ef0f9155b9247a86e",
|
||||
"url": "https://api.github.com/repos/pmmp/Language/zipball/aed64e9ca92ffbb20788b3b3bb75b60e4f0eae2d",
|
||||
"reference": "aed64e9ca92ffbb20788b3b3bb75b60e4f0eae2d",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -437,9 +437,9 @@
|
||||
"description": "Language resources used by PocketMine-MP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/Language/issues",
|
||||
"source": "https://github.com/pmmp/Language/tree/2.19.6"
|
||||
"source": "https://github.com/pmmp/Language/tree/2.22.0"
|
||||
},
|
||||
"time": "2023-08-08T16:53:23+00:00"
|
||||
"time": "2024-11-16T13:28:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/log",
|
||||
@ -926,16 +926,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v6.4.9",
|
||||
"version": "v6.4.13",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "b51ef8059159330b74a4d52f68e671033c0fe463"
|
||||
"reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463",
|
||||
"reference": "b51ef8059159330b74a4d52f68e671033c0fe463",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3",
|
||||
"reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -972,7 +972,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v6.4.9"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v6.4.13"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -988,24 +988,24 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-06-28T09:49:33+00:00"
|
||||
"time": "2024-10-25T15:07:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.30.0",
|
||||
"version": "v1.31.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "0424dff1c58f028c451efff2045f5d92410bd540"
|
||||
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540",
|
||||
"reference": "0424dff1c58f028c451efff2045f5d92410bd540",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
|
||||
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"provide": {
|
||||
"ext-ctype": "*"
|
||||
@ -1051,7 +1051,7 @@
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1067,24 +1067,24 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-31T15:07:36+00:00"
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.30.0",
|
||||
"version": "v1.31.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c"
|
||||
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c",
|
||||
"reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
|
||||
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"provide": {
|
||||
"ext-mbstring": "*"
|
||||
@ -1131,7 +1131,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1147,22 +1147,22 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-06-19T12:30:46+00:00"
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
"version": "1.12.0",
|
||||
"version": "1.12.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/DeepCopy.git",
|
||||
"reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c"
|
||||
"reference": "123267b2c49fbf30d78a7b2d333f6be754b94845"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
|
||||
"reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845",
|
||||
"reference": "123267b2c49fbf30d78a7b2d333f6be754b94845",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1201,7 +1201,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/myclabs/DeepCopy/issues",
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.12.0"
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.12.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1209,20 +1209,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-06-12T14:39:25+00:00"
|
||||
"time": "2024-11-08T17:47:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v5.0.2",
|
||||
"version": "v5.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13"
|
||||
"reference": "8eea230464783aa9671db8eea6f8c6ac5285794b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13",
|
||||
"reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b",
|
||||
"reference": "8eea230464783aa9671db8eea6f8c6ac5285794b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1233,7 +1233,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"ircmaxell/php-yacc": "^0.0.7",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
||||
"phpunit/phpunit": "^9.0"
|
||||
},
|
||||
"bin": [
|
||||
"bin/php-parse"
|
||||
@ -1265,9 +1265,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1"
|
||||
},
|
||||
"time": "2024-03-05T20:51:40+00:00"
|
||||
"time": "2024-10-08T18:51:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
@ -1389,16 +1389,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.11.10",
|
||||
"version": "1.11.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "640410b32995914bde3eed26fa89552f9c2c082f"
|
||||
"reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/640410b32995914bde3eed26fa89552f9c2c082f",
|
||||
"reference": "640410b32995914bde3eed26fa89552f9c2c082f",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/707c2aed5d8d0075666e673a5e71440c1d01a5a3",
|
||||
"reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1443,7 +1443,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-08-08T09:02:50+00:00"
|
||||
"time": "2024-08-19T14:37:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-phpunit",
|
||||
@ -1548,32 +1548,32 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "10.1.15",
|
||||
"version": "10.1.16",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae"
|
||||
"reference": "7e308268858ed6baedc8704a304727d20bc07c77"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae",
|
||||
"reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77",
|
||||
"reference": "7e308268858ed6baedc8704a304727d20bc07c77",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"nikic/php-parser": "^4.18 || ^5.0",
|
||||
"nikic/php-parser": "^4.19.1 || ^5.1.0",
|
||||
"php": ">=8.1",
|
||||
"phpunit/php-file-iterator": "^4.0",
|
||||
"phpunit/php-text-template": "^3.0",
|
||||
"sebastian/code-unit-reverse-lookup": "^3.0",
|
||||
"sebastian/complexity": "^3.0",
|
||||
"sebastian/environment": "^6.0",
|
||||
"sebastian/lines-of-code": "^2.0",
|
||||
"sebastian/version": "^4.0",
|
||||
"theseer/tokenizer": "^1.2.0"
|
||||
"phpunit/php-file-iterator": "^4.1.0",
|
||||
"phpunit/php-text-template": "^3.0.1",
|
||||
"sebastian/code-unit-reverse-lookup": "^3.0.0",
|
||||
"sebastian/complexity": "^3.2.0",
|
||||
"sebastian/environment": "^6.1.0",
|
||||
"sebastian/lines-of-code": "^2.0.2",
|
||||
"sebastian/version": "^4.0.1",
|
||||
"theseer/tokenizer": "^1.2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.1"
|
||||
@ -1585,7 +1585,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "10.1-dev"
|
||||
"dev-main": "10.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -1614,7 +1614,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.15"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1622,7 +1622,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-06-29T08:25:15+00:00"
|
||||
"time": "2024-08-22T04:31:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@ -1869,16 +1869,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "10.5.24",
|
||||
"version": "10.5.38",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "5f124e3e3e561006047b532fd0431bf5bb6b9015"
|
||||
"reference": "a86773b9e887a67bc53efa9da9ad6e3f2498c132"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5f124e3e3e561006047b532fd0431bf5bb6b9015",
|
||||
"reference": "5f124e3e3e561006047b532fd0431bf5bb6b9015",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a86773b9e887a67bc53efa9da9ad6e3f2498c132",
|
||||
"reference": "a86773b9e887a67bc53efa9da9ad6e3f2498c132",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1888,26 +1888,26 @@
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"myclabs/deep-copy": "^1.10.1",
|
||||
"phar-io/manifest": "^2.0.3",
|
||||
"phar-io/version": "^3.0.2",
|
||||
"myclabs/deep-copy": "^1.12.0",
|
||||
"phar-io/manifest": "^2.0.4",
|
||||
"phar-io/version": "^3.2.1",
|
||||
"php": ">=8.1",
|
||||
"phpunit/php-code-coverage": "^10.1.5",
|
||||
"phpunit/php-file-iterator": "^4.0",
|
||||
"phpunit/php-invoker": "^4.0",
|
||||
"phpunit/php-text-template": "^3.0",
|
||||
"phpunit/php-timer": "^6.0",
|
||||
"sebastian/cli-parser": "^2.0",
|
||||
"sebastian/code-unit": "^2.0",
|
||||
"sebastian/comparator": "^5.0",
|
||||
"sebastian/diff": "^5.0",
|
||||
"sebastian/environment": "^6.0",
|
||||
"sebastian/exporter": "^5.1",
|
||||
"sebastian/global-state": "^6.0.1",
|
||||
"sebastian/object-enumerator": "^5.0",
|
||||
"sebastian/recursion-context": "^5.0",
|
||||
"sebastian/type": "^4.0",
|
||||
"sebastian/version": "^4.0"
|
||||
"phpunit/php-code-coverage": "^10.1.16",
|
||||
"phpunit/php-file-iterator": "^4.1.0",
|
||||
"phpunit/php-invoker": "^4.0.0",
|
||||
"phpunit/php-text-template": "^3.0.1",
|
||||
"phpunit/php-timer": "^6.0.0",
|
||||
"sebastian/cli-parser": "^2.0.1",
|
||||
"sebastian/code-unit": "^2.0.0",
|
||||
"sebastian/comparator": "^5.0.3",
|
||||
"sebastian/diff": "^5.1.1",
|
||||
"sebastian/environment": "^6.1.0",
|
||||
"sebastian/exporter": "^5.1.2",
|
||||
"sebastian/global-state": "^6.0.2",
|
||||
"sebastian/object-enumerator": "^5.0.0",
|
||||
"sebastian/recursion-context": "^5.0.0",
|
||||
"sebastian/type": "^4.0.0",
|
||||
"sebastian/version": "^4.0.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-soap": "To be able to generate mocks based on WSDL files"
|
||||
@ -1950,7 +1950,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.24"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.38"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1966,7 +1966,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-06-20T13:09:54+00:00"
|
||||
"time": "2024-10-28T13:06:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
@ -2138,16 +2138,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/comparator",
|
||||
"version": "5.0.1",
|
||||
"version": "5.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/comparator.git",
|
||||
"reference": "2db5010a484d53ebf536087a70b4a5423c102372"
|
||||
"reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372",
|
||||
"reference": "2db5010a484d53ebf536087a70b4a5423c102372",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e",
|
||||
"reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2158,7 +2158,7 @@
|
||||
"sebastian/exporter": "^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.3"
|
||||
"phpunit/phpunit": "^10.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@ -2203,7 +2203,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/comparator/issues",
|
||||
"security": "https://github.com/sebastianbergmann/comparator/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1"
|
||||
"source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2211,7 +2211,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-08-14T13:18:12+00:00"
|
||||
"time": "2024-10-18T14:56:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/complexity",
|
||||
|
@ -40,6 +40,7 @@ parameters:
|
||||
- build/php
|
||||
dynamicConstantNames:
|
||||
- pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD
|
||||
- pocketmine\VersionInfo::BUILD_CHANNEL
|
||||
- pocketmine\DEBUG
|
||||
- pocketmine\IS_DEVELOPMENT_BUILD
|
||||
stubFiles:
|
||||
@ -47,8 +48,6 @@ parameters:
|
||||
- tests/phpstan/stubs/leveldb.stub
|
||||
- tests/phpstan/stubs/pmmpthread.stub
|
||||
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
|
||||
staticReflectionClassNamePatterns:
|
||||
- "#^COM$#"
|
||||
typeAliases:
|
||||
#variadics don't work for this - mixed probably shouldn't work either, but for now it does
|
||||
#what we actually need is something that accepts an infinite number of parameters, but in the absence of that,
|
||||
|
@ -332,7 +332,7 @@ class MemoryManager{
|
||||
continue;
|
||||
}
|
||||
$methodStatics = [];
|
||||
foreach($method->getStaticVariables() as $name => $variable){
|
||||
foreach(Utils::promoteKeys($method->getStaticVariables()) as $name => $variable){
|
||||
$methodStatics[$name] = self::continueDump($variable, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
if(count($methodStatics) > 0){
|
||||
@ -360,7 +360,7 @@ class MemoryManager{
|
||||
'_SESSION' => true
|
||||
];
|
||||
|
||||
foreach($GLOBALS as $varName => $value){
|
||||
foreach(Utils::promoteKeys($GLOBALS) as $varName => $value){
|
||||
if(isset($ignoredGlobals[$varName])){
|
||||
continue;
|
||||
}
|
||||
@ -376,7 +376,7 @@ class MemoryManager{
|
||||
$reflect = new \ReflectionFunction($function);
|
||||
|
||||
$vars = [];
|
||||
foreach($reflect->getStaticVariables() as $varName => $variable){
|
||||
foreach(Utils::promoteKeys($reflect->getStaticVariables()) as $varName => $variable){
|
||||
$vars[$varName] = self::continueDump($variable, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
if(count($vars) > 0){
|
||||
@ -416,7 +416,7 @@ class MemoryManager{
|
||||
$info["this"] = self::continueDump($closureThis, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
foreach($reflect->getStaticVariables() as $name => $variable){
|
||||
foreach(Utils::promoteKeys($reflect->getStaticVariables()) as $name => $variable){
|
||||
$info["referencedVars"][$name] = self::continueDump($variable, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
}else{
|
||||
@ -499,7 +499,7 @@ class MemoryManager{
|
||||
}
|
||||
$data = [];
|
||||
$numeric = 0;
|
||||
foreach($from as $key => $value){
|
||||
foreach(Utils::promoteKeys($from) as $key => $value){
|
||||
$data[$numeric] = [
|
||||
"k" => self::continueDump($key, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize),
|
||||
"v" => self::continueDump($value, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize),
|
||||
|
@ -89,6 +89,8 @@ use pocketmine\promise\Promise;
|
||||
use pocketmine\promise\PromiseResolver;
|
||||
use pocketmine\resourcepacks\ResourcePackManager;
|
||||
use pocketmine\scheduler\AsyncPool;
|
||||
use pocketmine\scheduler\TimingsCollectionTask;
|
||||
use pocketmine\scheduler\TimingsControlTask;
|
||||
use pocketmine\snooze\SleeperHandler;
|
||||
use pocketmine\stats\SendUsageTask;
|
||||
use pocketmine\thread\log\AttachableThreadSafeLogger;
|
||||
@ -736,12 +738,15 @@ class Server{
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
* @phpstan-return array<string, list<string>>
|
||||
*/
|
||||
public function getCommandAliases() : array{
|
||||
$section = $this->configGroup->getProperty(Yml::ALIASES);
|
||||
$result = [];
|
||||
if(is_array($section)){
|
||||
foreach($section as $key => $value){
|
||||
foreach(Utils::promoteKeys($section) as $key => $value){
|
||||
//TODO: more validation needed here
|
||||
//key might not be a string, value might not be list<string>
|
||||
$commands = [];
|
||||
if(is_array($value)){
|
||||
$commands = $value;
|
||||
@ -749,7 +754,7 @@ class Server{
|
||||
$commands[] = (string) $value;
|
||||
}
|
||||
|
||||
$result[$key] = $commands;
|
||||
$result[(string) $key] = $commands;
|
||||
}
|
||||
}
|
||||
|
||||
@ -891,7 +896,36 @@ class Server{
|
||||
$poolSize = max(1, (int) $poolSize);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
$this->asyncPool = new AsyncPool($poolSize, max(-1, $this->configGroup->getPropertyInt(Yml::MEMORY_ASYNC_WORKER_HARD_LIMIT, 256)), $this->autoloader, $this->logger, $this->tickSleeper);
|
||||
$this->asyncPool->addWorkerStartHook(function(int $i) : void{
|
||||
if(TimingsHandler::isEnabled()){
|
||||
$this->asyncPool->submitTaskToWorker(TimingsControlTask::setEnabled(true), $i);
|
||||
}
|
||||
});
|
||||
TimingsHandler::getToggleCallbacks()->add(function(bool $enable) : void{
|
||||
foreach($this->asyncPool->getRunningWorkers() as $workerId){
|
||||
$this->asyncPool->submitTaskToWorker(TimingsControlTask::setEnabled($enable), $workerId);
|
||||
}
|
||||
});
|
||||
TimingsHandler::getReloadCallbacks()->add(function() : void{
|
||||
foreach($this->asyncPool->getRunningWorkers() as $workerId){
|
||||
$this->asyncPool->submitTaskToWorker(TimingsControlTask::reload(), $workerId);
|
||||
}
|
||||
});
|
||||
TimingsHandler::getCollectCallbacks()->add(function() : array{
|
||||
$promises = [];
|
||||
foreach($this->asyncPool->getRunningWorkers() as $workerId){
|
||||
$resolver = new PromiseResolver();
|
||||
$this->asyncPool->submitTaskToWorker(new TimingsCollectionTask($resolver), $workerId);
|
||||
|
||||
$promises[] = $resolver->getPromise();
|
||||
}
|
||||
|
||||
return $promises;
|
||||
});
|
||||
|
||||
$netCompressionThreshold = -1;
|
||||
if($this->configGroup->getPropertyInt(Yml::NETWORK_BATCH_THRESHOLD, 256) >= 0){
|
||||
@ -965,9 +999,6 @@ class Server{
|
||||
)));
|
||||
$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);
|
||||
|
||||
DefaultPermissions::registerCorePermissions();
|
||||
|
||||
$this->commandMap = new SimpleCommandMap($this);
|
||||
@ -1094,7 +1125,11 @@ class Server{
|
||||
|
||||
$anyWorldFailedToLoad = false;
|
||||
|
||||
foreach((array) $this->configGroup->getProperty(Yml::WORLDS, []) as $name => $options){
|
||||
foreach(Utils::promoteKeys((array) $this->configGroup->getProperty(Yml::WORLDS, [])) as $name => $options){
|
||||
if(!is_string($name)){
|
||||
//TODO: this probably should be an error
|
||||
continue;
|
||||
}
|
||||
if($options === null){
|
||||
$options = [];
|
||||
}elseif(!is_array($options)){
|
||||
|
@ -31,8 +31,8 @@ use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "5.17.1";
|
||||
public const IS_DEVELOPMENT_BUILD = false;
|
||||
public const BASE_VERSION = "5.21.3";
|
||||
public const IS_DEVELOPMENT_BUILD = true;
|
||||
public const BUILD_CHANNEL = "stable";
|
||||
|
||||
/**
|
||||
|
@ -35,10 +35,10 @@ use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\AnvilFallSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use function lcg_value;
|
||||
use function round;
|
||||
|
||||
class Anvil extends Transparent implements Fallable{
|
||||
@ -97,7 +97,7 @@ class Anvil extends Transparent implements Fallable{
|
||||
}
|
||||
|
||||
public function onHitGround(FallingBlock $blockEntity) : bool{
|
||||
if(lcg_value() < 0.05 + (round($blockEntity->getFallDistance()) - 1) * 0.05){
|
||||
if(Utils::getRandomFloat() < 0.05 + (round($blockEntity->getFallDistance()) - 1) * 0.05){
|
||||
if($this->damage !== self::VERY_DAMAGED){
|
||||
$this->damage = $this->damage + 1;
|
||||
}else{
|
||||
|
@ -362,6 +362,8 @@ class Block{
|
||||
*
|
||||
* A replacement block may be returned. This is useful if the block type changed due to reading of world data (e.g.
|
||||
* data from a block entity).
|
||||
*
|
||||
* @phpstan-impure
|
||||
*/
|
||||
public function readStateFromWorld() : Block{
|
||||
return $this;
|
||||
|
@ -745,8 +745,28 @@ final class BlockTypeIds{
|
||||
public const PITCHER_PLANT = 10715;
|
||||
public const PITCHER_CROP = 10716;
|
||||
public const DOUBLE_PITCHER_CROP = 10717;
|
||||
public const CAMPFIRE = 10718;
|
||||
public const SOUL_CAMPFIRE = 10719;
|
||||
public const TUFF_SLAB = 10720;
|
||||
public const TUFF_STAIRS = 10721;
|
||||
public const TUFF_WALL = 10722;
|
||||
public const CHISELED_TUFF = 10723;
|
||||
public const TUFF_BRICKS = 10724;
|
||||
public const TUFF_BRICK_SLAB = 10725;
|
||||
public const TUFF_BRICK_STAIRS = 10726;
|
||||
public const TUFF_BRICK_WALL = 10727;
|
||||
public const CHISELED_TUFF_BRICKS = 10728;
|
||||
public const POLISHED_TUFF = 10729;
|
||||
public const POLISHED_TUFF_SLAB = 10730;
|
||||
public const POLISHED_TUFF_STAIRS = 10731;
|
||||
public const POLISHED_TUFF_WALL = 10732;
|
||||
public const COPPER_BULB = 10733;
|
||||
public const COPPER_DOOR = 10734;
|
||||
public const COPPER_TRAPDOOR = 10735;
|
||||
public const CHISELED_COPPER = 10736;
|
||||
public const COPPER_GRATE = 10737;
|
||||
|
||||
public const FIRST_UNUSED_BLOCK_ID = 10718;
|
||||
public const FIRST_UNUSED_BLOCK_ID = 10738;
|
||||
|
||||
private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID;
|
||||
|
||||
|
@ -27,10 +27,6 @@ use pocketmine\item\Item;
|
||||
|
||||
class BlueIce extends Opaque{
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getFrictionFactor() : float{
|
||||
return 0.99;
|
||||
}
|
||||
@ -38,4 +34,8 @@ class BlueIce extends Opaque{
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,9 @@ class CakeWithCandle extends BaseCake{
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($this->lit && $face !== Facing::UP){
|
||||
return true;
|
||||
}
|
||||
if($this->onInteractCandle($item, $face, $clickVector, $player, $returnedItems)){
|
||||
return true;
|
||||
}
|
||||
|
285
src/block/Campfire.php
Normal file
285
src/block/Campfire.php
Normal file
@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\inventory\CampfireInventory;
|
||||
use pocketmine\block\tile\Campfire as TileCampfire;
|
||||
use pocketmine\block\utils\HorizontalFacingTrait;
|
||||
use pocketmine\block\utils\LightableTrait;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\crafting\FurnaceRecipe;
|
||||
use pocketmine\crafting\FurnaceType;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\entity\projectile\Projectile;
|
||||
use pocketmine\entity\projectile\SplashPotion;
|
||||
use pocketmine\event\block\CampfireCookEvent;
|
||||
use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\item\Durable;
|
||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemTypeIds;
|
||||
use pocketmine\item\PotionType;
|
||||
use pocketmine\item\Shovel;
|
||||
use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\RayTraceResult;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\BlazeShootSound;
|
||||
use pocketmine\world\sound\FireExtinguishSound;
|
||||
use pocketmine\world\sound\FlintSteelSound;
|
||||
use pocketmine\world\sound\ItemFrameAddItemSound;
|
||||
use function count;
|
||||
use function min;
|
||||
use function mt_rand;
|
||||
|
||||
class Campfire extends Transparent{
|
||||
use HorizontalFacingTrait{
|
||||
HorizontalFacingTrait::describeBlockOnlyState as encodeFacingState;
|
||||
}
|
||||
use LightableTrait{
|
||||
LightableTrait::describeBlockOnlyState as encodeLitState;
|
||||
}
|
||||
|
||||
private const UPDATE_INTERVAL_TICKS = 10;
|
||||
|
||||
/**
|
||||
* @deprecated This was added by mistake. It can't be relied on as the inventory won't be initialized if this block
|
||||
* has never been set in the world.
|
||||
*/
|
||||
protected CampfireInventory $inventory;
|
||||
|
||||
/**
|
||||
* @var int[] slot => ticks
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
protected array $cookingTimes = [];
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$this->encodeFacingState($w);
|
||||
$this->encodeLitState($w);
|
||||
}
|
||||
|
||||
public function readStateFromWorld() : Block{
|
||||
parent::readStateFromWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
if($tile instanceof TileCampfire){
|
||||
$this->inventory = $tile->getInventory();
|
||||
$this->cookingTimes = $tile->getCookingTimes();
|
||||
}else{
|
||||
$this->inventory = new CampfireInventory($this->position);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
if($tile instanceof TileCampfire){
|
||||
$tile->setCookingTimes($this->cookingTimes);
|
||||
}
|
||||
}
|
||||
|
||||
public function hasEntityCollision() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return $this->lit ? 15 : 0;
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
VanillaItems::CHARCOAL()->setCount(2)
|
||||
];
|
||||
}
|
||||
|
||||
public function getSupportType(int $facing) : SupportType{
|
||||
return SupportType::NONE;
|
||||
}
|
||||
|
||||
protected function recalculateCollisionBoxes() : array{
|
||||
return [AxisAlignedBB::one()->trim(Facing::UP, 9 / 16)];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This was added by mistake. It can't be relied on as the inventory won't be initialized if this block
|
||||
* has never been set in the world.
|
||||
*/
|
||||
public function getInventory() : CampfireInventory{
|
||||
return $this->inventory;
|
||||
}
|
||||
|
||||
protected function getFurnaceType() : FurnaceType{
|
||||
return FurnaceType::CAMPFIRE;
|
||||
}
|
||||
|
||||
protected function getEntityCollisionDamage() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of ticks during the item in the given slot has been cooked.
|
||||
*/
|
||||
public function setCookingTime(int $slot, int $time) : void{
|
||||
if($slot < 0 || $slot > 3){
|
||||
throw new \InvalidArgumentException("Slot must be in range 0-3");
|
||||
}
|
||||
if($time < 0 || $time > $this->getFurnaceType()->getCookDurationTicks()){
|
||||
throw new \InvalidArgumentException("CookingTime must be in range 0-" . $this->getFurnaceType()->getCookDurationTicks());
|
||||
}
|
||||
$this->cookingTimes[$slot] = $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of ticks during the item in the given slot has been cooked.
|
||||
*/
|
||||
public function getCookingTime(int $slot) : int{
|
||||
return $this->cookingTimes[$slot] ?? 0;
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if($this->getSide(Facing::DOWN) instanceof Campfire){
|
||||
return false;
|
||||
}
|
||||
if($player !== null){
|
||||
$this->facing = $player->getHorizontalFacing();
|
||||
}
|
||||
$this->lit = true;
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if(!$this->lit){
|
||||
if($item->getTypeId() === ItemTypeIds::FIRE_CHARGE){
|
||||
$item->pop();
|
||||
$this->ignite();
|
||||
$this->position->getWorld()->addSound($this->position, new BlazeShootSound());
|
||||
return true;
|
||||
}elseif($item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
|
||||
if($item instanceof Durable){
|
||||
$item->applyDamage(1);
|
||||
}
|
||||
$this->ignite();
|
||||
return true;
|
||||
}
|
||||
}elseif($item instanceof Shovel){
|
||||
$item->applyDamage(1);
|
||||
$this->extinguish();
|
||||
return true;
|
||||
}
|
||||
|
||||
if($this->position->getWorld()->getServer()->getCraftingManager()->getFurnaceRecipeManager($this->getFurnaceType())->match($item) !== null){
|
||||
$ingredient = clone $item;
|
||||
$ingredient->setCount(1);
|
||||
if(count($this->inventory->addItem($ingredient)) === 0){
|
||||
$item->pop();
|
||||
$this->position->getWorld()->addSound($this->position, new ItemFrameAddItemSound());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->lit && $this->getSide(Facing::UP)->getTypeId() === BlockTypeIds::WATER){
|
||||
$this->extinguish();
|
||||
//TODO: Waterlogging
|
||||
}
|
||||
}
|
||||
|
||||
public function onEntityInside(Entity $entity) : bool{
|
||||
if(!$this->lit){
|
||||
if($entity->isOnFire()){
|
||||
$this->ignite();
|
||||
return false;
|
||||
}
|
||||
}elseif($entity instanceof Living){
|
||||
$entity->attack(new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, $this->getEntityCollisionDamage()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
|
||||
if($this->lit && $projectile instanceof SplashPotion && $projectile->getPotionType() === PotionType::WATER){
|
||||
$this->extinguish();
|
||||
}
|
||||
}
|
||||
|
||||
public function onScheduledUpdate() : void{
|
||||
if($this->lit){
|
||||
$items = $this->inventory->getContents();
|
||||
$furnaceType = $this->getFurnaceType();
|
||||
$maxCookDuration = $furnaceType->getCookDurationTicks();
|
||||
foreach($items as $slot => $item){
|
||||
$this->setCookingTime($slot, min($maxCookDuration, $this->getCookingTime($slot) + self::UPDATE_INTERVAL_TICKS));
|
||||
if($this->getCookingTime($slot) >= $maxCookDuration){
|
||||
$result =
|
||||
($recipe = $this->position->getWorld()->getServer()->getCraftingManager()->getFurnaceRecipeManager($furnaceType)->match($item)) instanceof FurnaceRecipe ?
|
||||
$recipe->getResult() :
|
||||
VanillaItems::AIR();
|
||||
|
||||
$ev = new CampfireCookEvent($this, $slot, $item, $result);
|
||||
$ev->call();
|
||||
|
||||
if ($ev->isCancelled()){
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->inventory->setItem($slot, VanillaItems::AIR());
|
||||
$this->setCookingTime($slot, 0);
|
||||
$this->position->getWorld()->dropItem($this->position->add(0.5, 1, 0.5), $ev->getResult());
|
||||
}
|
||||
}
|
||||
if(count($items) > 0){
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
}
|
||||
if(mt_rand(1, 6) === 1){
|
||||
$this->position->getWorld()->addSound($this->position, $furnaceType->getCookSound());
|
||||
}
|
||||
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, self::UPDATE_INTERVAL_TICKS);
|
||||
}
|
||||
}
|
||||
|
||||
private function extinguish() : void{
|
||||
$this->position->getWorld()->addSound($this->position, new FireExtinguishSound());
|
||||
$this->position->getWorld()->setBlock($this->position, $this->setLit(false));
|
||||
}
|
||||
|
||||
private function ignite() : void{
|
||||
$this->position->getWorld()->addSound($this->position, new FlintSteelSound());
|
||||
$this->position->getWorld()->setBlock($this->position, $this->setLit(true));
|
||||
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, self::UPDATE_INTERVAL_TICKS);
|
||||
}
|
||||
}
|
@ -48,11 +48,32 @@ class ChiseledBookshelf extends Opaque{
|
||||
*/
|
||||
private array $slots = [];
|
||||
|
||||
private ?ChiseledBookshelfSlot $lastInteractedSlot = null;
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->horizontalFacing($this->facing);
|
||||
$w->enumSet($this->slots, ChiseledBookshelfSlot::cases());
|
||||
}
|
||||
|
||||
public function readStateFromWorld() : Block{
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
if($tile instanceof TileChiseledBookshelf){
|
||||
$this->lastInteractedSlot = $tile->getLastInteractedSlot();
|
||||
}else{
|
||||
$this->lastInteractedSlot = null;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function writeStateToWorld() : void{
|
||||
parent::writeStateToWorld();
|
||||
|
||||
$tile = $this->position->getWorld()->getTile($this->position);
|
||||
if($tile instanceof TileChiseledBookshelf){
|
||||
$tile->setLastInteractedSlot($this->lastInteractedSlot);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given slot is displayed as occupied.
|
||||
* This doesn't guarantee that there is or isn't a book in the bookshelf's inventory.
|
||||
@ -92,6 +113,23 @@ class ChiseledBookshelf extends Opaque{
|
||||
return $this->slots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last slot interacted by a player or null if no slot has been interacted with yet.
|
||||
*/
|
||||
public function getLastInteractedSlot() : ?ChiseledBookshelfSlot{
|
||||
return $this->lastInteractedSlot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last slot interacted by a player.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setLastInteractedSlot(?ChiseledBookshelfSlot $lastInteractedSlot) : self{
|
||||
$this->lastInteractedSlot = $lastInteractedSlot;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($face !== $this->facing){
|
||||
return false;
|
||||
@ -112,10 +150,12 @@ class ChiseledBookshelf extends Opaque{
|
||||
$returnedItems[] = $inventory->getItem($slot->value);
|
||||
$inventory->clear($slot->value);
|
||||
$this->setSlot($slot, false);
|
||||
$this->lastInteractedSlot = $slot;
|
||||
}elseif($item instanceof WritableBookBase || $item instanceof Book || $item instanceof EnchantedBook){
|
||||
//TODO: type tags like blocks would be better for this
|
||||
$inventory->setItem($slot->value, $item->pop());
|
||||
$this->setSlot($slot, true);
|
||||
$this->lastInteractedSlot = $slot;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
|
@ -23,8 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\CopperMaterial;
|
||||
use pocketmine\block\utils\CopperTrait;
|
||||
|
||||
class Copper extends Opaque{
|
||||
class Copper extends Opaque implements CopperMaterial{
|
||||
use CopperTrait;
|
||||
}
|
||||
|
69
src/block/CopperBulb.php
Normal file
69
src/block/CopperBulb.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\CopperMaterial;
|
||||
use pocketmine\block\utils\CopperOxidation;
|
||||
use pocketmine\block\utils\CopperTrait;
|
||||
use pocketmine\block\utils\LightableTrait;
|
||||
use pocketmine\block\utils\PoweredByRedstoneTrait;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
|
||||
class CopperBulb extends Opaque implements CopperMaterial{
|
||||
use CopperTrait;
|
||||
use PoweredByRedstoneTrait;
|
||||
use LightableTrait{
|
||||
describeBlockOnlyState as encodeLitState;
|
||||
}
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$this->encodeLitState($w);
|
||||
$w->bool($this->powered);
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function togglePowered(bool $powered) : self{
|
||||
if($powered === $this->powered){
|
||||
return $this;
|
||||
}
|
||||
if ($powered) {
|
||||
$this->setLit(!$this->lit);
|
||||
}
|
||||
$this->setPowered($powered);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
if ($this->lit) {
|
||||
return match($this->oxidation){
|
||||
CopperOxidation::NONE => 15,
|
||||
CopperOxidation::EXPOSED => 12,
|
||||
CopperOxidation::WEATHERED => 8,
|
||||
CopperOxidation::OXIDIZED => 4,
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
53
src/block/CopperDoor.php
Normal file
53
src/block/CopperDoor.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\CopperMaterial;
|
||||
use pocketmine\block\utils\CopperTrait;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
|
||||
class CopperDoor extends Door implements CopperMaterial{
|
||||
use CopperTrait{
|
||||
onInteract as onInteractCopper;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if ($player !== null && $player->isSneaking() && $this->onInteractCopper($item, $face, $clickVector, $player, $returnedItems)) {
|
||||
//copy copper properties to other half
|
||||
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||
$world = $this->position->getWorld();
|
||||
if ($other instanceof CopperDoor) {
|
||||
$other->setOxidation($this->oxidation);
|
||||
$other->setWaxed($this->waxed);
|
||||
$world->setBlock($other->position, $other);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
|
||||
}
|
||||
}
|
33
src/block/CopperGrate.php
Normal file
33
src/block/CopperGrate.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\CopperMaterial;
|
||||
use pocketmine\block\utils\CopperTrait;
|
||||
|
||||
class CopperGrate extends Transparent implements CopperMaterial{
|
||||
use CopperTrait;
|
||||
|
||||
//TODO: waterlogging!
|
||||
}
|
@ -23,8 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\CopperMaterial;
|
||||
use pocketmine\block\utils\CopperTrait;
|
||||
|
||||
class CopperSlab extends Slab{
|
||||
class CopperSlab extends Slab implements CopperMaterial{
|
||||
use CopperTrait;
|
||||
}
|
||||
|
@ -23,8 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\CopperMaterial;
|
||||
use pocketmine\block\utils\CopperTrait;
|
||||
|
||||
class CopperStairs extends Stair{
|
||||
class CopperStairs extends Stair implements CopperMaterial{
|
||||
use CopperTrait;
|
||||
}
|
||||
|
44
src/block/CopperTrapdoor.php
Normal file
44
src/block/CopperTrapdoor.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\CopperMaterial;
|
||||
use pocketmine\block\utils\CopperTrait;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
|
||||
class CopperTrapdoor extends Trapdoor implements CopperMaterial{
|
||||
use CopperTrait{
|
||||
onInteract as onInteractCopper;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if ($player !== null && $player->isSneaking() && $this->onInteractCopper($item, $face, $clickVector, $player, $returnedItems)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\event\block\BlockTeleportEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\GameMode;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\particle\DragonEggTeleportParticle;
|
||||
use pocketmine\world\World;
|
||||
@ -50,7 +50,7 @@ class DragonEgg extends Transparent implements Fallable{
|
||||
}
|
||||
|
||||
public function onAttack(Item $item, int $face, ?Player $player = null) : bool{
|
||||
if($player !== null && $player->getGamemode() !== GameMode::CREATIVE){
|
||||
if($player !== null && !$player->hasPermission(DefaultPermissionNames::GAME_BLOCK_DELETE)){
|
||||
$this->teleport();
|
||||
return true;
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ use pocketmine\event\entity\EntityTrampleFarmlandEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\utils\Utils;
|
||||
use function intdiv;
|
||||
use function lcg_value;
|
||||
|
||||
class Farmland extends Transparent{
|
||||
public const MAX_WETNESS = 7;
|
||||
@ -148,7 +148,7 @@ class Farmland extends Transparent{
|
||||
}
|
||||
|
||||
public function onEntityLand(Entity $entity) : ?float{
|
||||
if($entity instanceof Living && lcg_value() < $entity->getFallDistance() - 0.5){
|
||||
if($entity instanceof Living && Utils::getRandomFloat() < $entity->getFallDistance() - 0.5){
|
||||
$ev = new EntityTrampleFarmlandEvent($entity, $this);
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
/**
|
||||
* "Flowable" blocks are destroyed if water flows into the same space as the block. These blocks usually don't have any
|
||||
@ -40,6 +41,11 @@ abstract class Flowable extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
|
||||
return (!$this->canBeFlowedInto() || !$blockReplace instanceof Liquid) &&
|
||||
parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB[]
|
||||
*/
|
||||
|
@ -24,60 +24,20 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockEventHelper;
|
||||
use pocketmine\block\utils\MultiAnySupportTrait;
|
||||
use pocketmine\block\utils\SupportType;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\World;
|
||||
use function array_key_first;
|
||||
use function count;
|
||||
use function shuffle;
|
||||
|
||||
class GlowLichen extends Transparent{
|
||||
|
||||
/** @var int[] */
|
||||
protected array $faces = [];
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->facingFlags($this->faces);
|
||||
}
|
||||
|
||||
/** @return int[] */
|
||||
public function getFaces() : array{ return $this->faces; }
|
||||
|
||||
public function hasFace(int $face) : bool{
|
||||
return isset($this->faces[$face]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $faces
|
||||
* @return $this
|
||||
*/
|
||||
public function setFaces(array $faces) : self{
|
||||
$uniqueFaces = [];
|
||||
foreach($faces as $face){
|
||||
Facing::validate($face);
|
||||
$uniqueFaces[$face] = $face;
|
||||
}
|
||||
$this->faces = $uniqueFaces;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function setFace(int $face, bool $value) : self{
|
||||
Facing::validate($face);
|
||||
if($value){
|
||||
$this->faces[$face] = $face;
|
||||
}else{
|
||||
unset($this->faces[$face]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
use MultiAnySupportTrait;
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return 7;
|
||||
@ -102,39 +62,11 @@ class GlowLichen extends Transparent{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$this->faces = $blockReplace instanceof GlowLichen ? $blockReplace->faces : [];
|
||||
$availableFaces = $this->getAvailableFaces();
|
||||
|
||||
if(count($availableFaces) === 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
$opposite = Facing::opposite($face);
|
||||
$placedFace = isset($availableFaces[$opposite]) ? $opposite : array_key_first($availableFaces);
|
||||
$this->faces[$placedFace] = $placedFace;
|
||||
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$changed = false;
|
||||
|
||||
foreach($this->faces as $face){
|
||||
if($this->getAdjacentSupportType($face) !== SupportType::FULL){
|
||||
unset($this->faces[$face]);
|
||||
$changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if($changed){
|
||||
$world = $this->position->getWorld();
|
||||
if(count($this->faces) === 0){
|
||||
$world->useBreakOn($this->position);
|
||||
}else{
|
||||
$world->setBlock($this->position, $this);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
protected function getInitialPlaceFaces(Block $blockReplace) : array{
|
||||
return $blockReplace instanceof GlowLichen ? $blockReplace->faces : [];
|
||||
}
|
||||
|
||||
private function getSpreadBlock(Block $replace, int $spreadFace) : ?Block{
|
||||
@ -261,17 +193,4 @@ class GlowLichen extends Transparent{
|
||||
public function getFlammability() : int{
|
||||
return 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, int> $faces
|
||||
*/
|
||||
private function getAvailableFaces() : array{
|
||||
$faces = [];
|
||||
foreach(Facing::ALL as $face){
|
||||
if(!$this->hasFace($face) && $this->getAdjacentSupportType($face) === SupportType::FULL){
|
||||
$faces[$face] = $face;
|
||||
}
|
||||
}
|
||||
return $faces;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
||||
use pocketmine\block\utils\BlockEventHelper;
|
||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
|
||||
class Ice extends Transparent{
|
||||
@ -39,7 +40,8 @@ class Ice extends Transparent{
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if(($player === null || $player->isSurvival()) && !$item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
|
||||
//TODO: we should probably pass instaBreak in here, since events can override it
|
||||
if(($player === null || !$player->hasPermission(DefaultPermissionNames::GAME_BLOCK_DELETE)) && !$item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
|
||||
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::WATER());
|
||||
return true;
|
||||
}
|
||||
|
@ -31,13 +31,13 @@ use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use pocketmine\world\sound\ItemFrameAddItemSound;
|
||||
use pocketmine\world\sound\ItemFrameRemoveItemSound;
|
||||
use pocketmine\world\sound\ItemFrameRotateItemSound;
|
||||
use function is_infinite;
|
||||
use function is_nan;
|
||||
use function lcg_value;
|
||||
|
||||
class ItemFrame extends Flowable{
|
||||
use AnyFacingTrait;
|
||||
@ -154,7 +154,7 @@ class ItemFrame extends Flowable{
|
||||
return false;
|
||||
}
|
||||
$world = $this->position->getWorld();
|
||||
if(lcg_value() <= $this->itemDropChance){
|
||||
if(Utils::getRandomFloat() <= $this->itemDropChance){
|
||||
$world->dropItem($this->position->add(0.5, 0.5, 0.5), clone $this->framedItem);
|
||||
$world->addSound($this->position, new ItemFrameRemoveItemSound());
|
||||
}
|
||||
@ -185,7 +185,7 @@ class ItemFrame extends Flowable{
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
$drops = parent::getDropsForCompatibleTool($item);
|
||||
if($this->framedItem !== null && lcg_value() <= $this->itemDropChance){
|
||||
if($this->framedItem !== null && Utils::getRandomFloat() <= $this->itemDropChance){
|
||||
$drops[] = clone $this->framedItem;
|
||||
}
|
||||
|
||||
|
@ -33,9 +33,9 @@ use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\world\sound\FizzSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use function lcg_value;
|
||||
|
||||
abstract class Liquid extends Transparent{
|
||||
public const MAX_DECAY = 7;
|
||||
@ -368,7 +368,7 @@ abstract class Liquid extends Transparent{
|
||||
|
||||
protected function liquidCollide(Block $cause, Block $result) : bool{
|
||||
if(BlockEventHelper::form($this, $result, $cause)){
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new FizzSound(2.6 + (lcg_value() - lcg_value()) * 0.8));
|
||||
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new FizzSound(2.6 + (Utils::getRandomFloat() - Utils::getRandomFloat()) * 0.8));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class Magma extends Opaque{
|
||||
}
|
||||
|
||||
public function onEntityInside(Entity $entity) : bool{
|
||||
if($entity instanceof Living && !$entity->isSneaking()){
|
||||
if($entity instanceof Living && !$entity->isSneaking() && $entity->getFrostWalkerLevel() === 0){
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
|
||||
$entity->attack($ev);
|
||||
}
|
||||
|
@ -132,6 +132,7 @@ class RuntimeBlockStateRegistry{
|
||||
|
||||
/**
|
||||
* @return Block[]
|
||||
* @phpstan-return array<int, Block>
|
||||
*/
|
||||
public function getAllKnownStates() : array{
|
||||
return $this->fullList;
|
||||
|
48
src/block/SoulCampfire.php
Normal file
48
src/block/SoulCampfire.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\crafting\FurnaceType;
|
||||
use pocketmine\item\Item;
|
||||
|
||||
class SoulCampfire extends Campfire{
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return $this->lit ? 10 : 0;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
VanillaBlocks::SOUL_SOIL()->asItem()
|
||||
];
|
||||
}
|
||||
|
||||
protected function getEntityCollisionDamage() : int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
protected function getFurnaceType() : FurnaceType{
|
||||
return FurnaceType::SOUL_CAMPFIRE;
|
||||
}
|
||||
}
|
@ -36,7 +36,9 @@ use pocketmine\world\Position;
|
||||
|
||||
class Sugarcane extends Flowable{
|
||||
use AgeableTrait;
|
||||
use StaticSupportTrait;
|
||||
use StaticSupportTrait {
|
||||
onNearbyBlockChange as onSupportBlockChange;
|
||||
}
|
||||
|
||||
public const MAX_AGE = 15;
|
||||
|
||||
@ -97,7 +99,13 @@ class Sugarcane extends Flowable{
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if(!$this->getSide(Facing::DOWN)->hasSameTypeId($this)){
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
if(!$down->hasSameTypeId($this)){
|
||||
if(!$this->hasNearbyWater($down)){
|
||||
$this->position->getWorld()->useBreakOn($this->position, createParticles: true);
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->age === self::MAX_AGE){
|
||||
$this->grow($this->position);
|
||||
}else{
|
||||
@ -123,4 +131,23 @@ class Sugarcane extends Flowable{
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function hasNearbyWater(Block $down) : bool{
|
||||
foreach($down->getHorizontalSides() as $sideBlock){
|
||||
$blockId = $sideBlock->getTypeId();
|
||||
if($blockId === BlockTypeIds::WATER || $blockId === BlockTypeIds::FROSTED_ICE){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
if(!$down->hasSameTypeId($this) && !$this->hasNearbyWater($down)){
|
||||
$this->position->getWorld()->useBreakOn($this->position, createParticles: true);
|
||||
}else{
|
||||
$this->onSupportBlockChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,263 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\BlockIdentifier as BID;
|
||||
use pocketmine\block\BlockTypeIds as Ids;
|
||||
use pocketmine\block\tile\Sign as TileSign;
|
||||
use pocketmine\block\utils\LeavesType;
|
||||
use pocketmine\block\utils\SaplingType;
|
||||
use pocketmine\block\utils\WoodType;
|
||||
use pocketmine\item\VanillaItems;
|
||||
|
||||
/**
|
||||
* All wood-like blocks have different IDs for different wood types.
|
||||
*
|
||||
* We can't make these dynamic, because some types of wood have different type properties (e.g. crimson and warped planks
|
||||
* are not flammable, but all other planks are).
|
||||
*
|
||||
* In the future, it's entirely within the realm of reason that the other types of wood may differ in other ways, such
|
||||
* as flammability, hardness, required tool tier, etc.
|
||||
* Therefore, to stay on the safe side of Mojang, wood-like blocks have static types. This does unfortunately generate
|
||||
* a lot of ugly code.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class WoodLikeBlockIdHelper{
|
||||
|
||||
public static function getPlanksIdentifier(WoodType $type) : BID{
|
||||
return new BID(match($type){
|
||||
WoodType::OAK => Ids::OAK_PLANKS,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_PLANKS,
|
||||
WoodType::BIRCH => Ids::BIRCH_PLANKS,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_PLANKS,
|
||||
WoodType::ACACIA => Ids::ACACIA_PLANKS,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_PLANKS,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_PLANKS,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_PLANKS,
|
||||
WoodType::WARPED => Ids::WARPED_PLANKS,
|
||||
WoodType::CHERRY => Ids::CHERRY_PLANKS,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getFenceIdentifier(WoodType $type) : BID{
|
||||
return new BID(match($type){
|
||||
WoodType::OAK => Ids::OAK_FENCE,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_FENCE,
|
||||
WoodType::BIRCH => Ids::BIRCH_FENCE,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_FENCE,
|
||||
WoodType::ACACIA => Ids::ACACIA_FENCE,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_FENCE,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_FENCE,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_FENCE,
|
||||
WoodType::WARPED => Ids::WARPED_FENCE,
|
||||
WoodType::CHERRY => Ids::CHERRY_FENCE,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getSlabIdentifier(WoodType $type) : BID{
|
||||
return new BID(match($type){
|
||||
WoodType::OAK => Ids::OAK_SLAB,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_SLAB,
|
||||
WoodType::BIRCH => Ids::BIRCH_SLAB,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_SLAB,
|
||||
WoodType::ACACIA => Ids::ACACIA_SLAB,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_SLAB,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_SLAB,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_SLAB,
|
||||
WoodType::WARPED => Ids::WARPED_SLAB,
|
||||
WoodType::CHERRY => Ids::CHERRY_SLAB,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getLogIdentifier(WoodType $treeType) : BID{
|
||||
return new BID(match($treeType){
|
||||
WoodType::OAK => Ids::OAK_LOG,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_LOG,
|
||||
WoodType::BIRCH => Ids::BIRCH_LOG,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_LOG,
|
||||
WoodType::ACACIA => Ids::ACACIA_LOG,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_LOG,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_LOG,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_STEM,
|
||||
WoodType::WARPED => Ids::WARPED_STEM,
|
||||
WoodType::CHERRY => Ids::CHERRY_LOG,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getAllSidedLogIdentifier(WoodType $treeType) : BID{
|
||||
return new BID(match($treeType){
|
||||
WoodType::OAK => Ids::OAK_WOOD,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_WOOD,
|
||||
WoodType::BIRCH => Ids::BIRCH_WOOD,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_WOOD,
|
||||
WoodType::ACACIA => Ids::ACACIA_WOOD,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_WOOD,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_WOOD,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_HYPHAE,
|
||||
WoodType::WARPED => Ids::WARPED_HYPHAE,
|
||||
WoodType::CHERRY => Ids::CHERRY_WOOD,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getLeavesIdentifier(LeavesType $leavesType) : BID{
|
||||
return new BID(match($leavesType){
|
||||
LeavesType::OAK => Ids::OAK_LEAVES,
|
||||
LeavesType::SPRUCE => Ids::SPRUCE_LEAVES,
|
||||
LeavesType::BIRCH => Ids::BIRCH_LEAVES,
|
||||
LeavesType::JUNGLE => Ids::JUNGLE_LEAVES,
|
||||
LeavesType::ACACIA => Ids::ACACIA_LEAVES,
|
||||
LeavesType::DARK_OAK => Ids::DARK_OAK_LEAVES,
|
||||
LeavesType::MANGROVE => Ids::MANGROVE_LEAVES,
|
||||
LeavesType::AZALEA => Ids::AZALEA_LEAVES,
|
||||
LeavesType::FLOWERING_AZALEA => Ids::FLOWERING_AZALEA_LEAVES,
|
||||
LeavesType::CHERRY => Ids::CHERRY_LEAVES,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getSaplingIdentifier(SaplingType $treeType) : BID{
|
||||
return new BID(match($treeType){
|
||||
SaplingType::OAK => Ids::OAK_SAPLING,
|
||||
SaplingType::SPRUCE => Ids::SPRUCE_SAPLING,
|
||||
SaplingType::BIRCH => Ids::BIRCH_SAPLING,
|
||||
SaplingType::JUNGLE => Ids::JUNGLE_SAPLING,
|
||||
SaplingType::ACACIA => Ids::ACACIA_SAPLING,
|
||||
SaplingType::DARK_OAK => Ids::DARK_OAK_SAPLING,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BID[]|\Closure[]
|
||||
* @phpstan-return array{BID, BID, \Closure() : \pocketmine\item\Item}
|
||||
*/
|
||||
public static function getSignInfo(WoodType $treeType) : array{
|
||||
$make = fn(int $floorId, int $wallId, \Closure $getItem) => [
|
||||
new BID($floorId, TileSign::class),
|
||||
new BID($wallId, TileSign::class),
|
||||
$getItem
|
||||
];
|
||||
return match($treeType){
|
||||
WoodType::OAK => $make(Ids::OAK_SIGN, Ids::OAK_WALL_SIGN, fn() => VanillaItems::OAK_SIGN()),
|
||||
WoodType::SPRUCE => $make(Ids::SPRUCE_SIGN, Ids::SPRUCE_WALL_SIGN, fn() => VanillaItems::SPRUCE_SIGN()),
|
||||
WoodType::BIRCH => $make(Ids::BIRCH_SIGN, Ids::BIRCH_WALL_SIGN, fn() => VanillaItems::BIRCH_SIGN()),
|
||||
WoodType::JUNGLE => $make(Ids::JUNGLE_SIGN, Ids::JUNGLE_WALL_SIGN, fn() => VanillaItems::JUNGLE_SIGN()),
|
||||
WoodType::ACACIA => $make(Ids::ACACIA_SIGN, Ids::ACACIA_WALL_SIGN, fn() => VanillaItems::ACACIA_SIGN()),
|
||||
WoodType::DARK_OAK => $make(Ids::DARK_OAK_SIGN, Ids::DARK_OAK_WALL_SIGN, fn() => VanillaItems::DARK_OAK_SIGN()),
|
||||
WoodType::MANGROVE => $make(Ids::MANGROVE_SIGN, Ids::MANGROVE_WALL_SIGN, fn() => VanillaItems::MANGROVE_SIGN()),
|
||||
WoodType::CRIMSON => $make(Ids::CRIMSON_SIGN, Ids::CRIMSON_WALL_SIGN, fn() => VanillaItems::CRIMSON_SIGN()),
|
||||
WoodType::WARPED => $make(Ids::WARPED_SIGN, Ids::WARPED_WALL_SIGN, fn() => VanillaItems::WARPED_SIGN()),
|
||||
WoodType::CHERRY => $make(Ids::CHERRY_SIGN, Ids::CHERRY_WALL_SIGN, fn() => VanillaItems::CHERRY_SIGN()),
|
||||
};
|
||||
}
|
||||
|
||||
public static function getTrapdoorIdentifier(WoodType $treeType) : BID{
|
||||
return new BID(match($treeType){
|
||||
WoodType::OAK => Ids::OAK_TRAPDOOR,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_TRAPDOOR,
|
||||
WoodType::BIRCH => Ids::BIRCH_TRAPDOOR,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_TRAPDOOR,
|
||||
WoodType::ACACIA => Ids::ACACIA_TRAPDOOR,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_TRAPDOOR,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_TRAPDOOR,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_TRAPDOOR,
|
||||
WoodType::WARPED => Ids::WARPED_TRAPDOOR,
|
||||
WoodType::CHERRY => Ids::CHERRY_TRAPDOOR,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getButtonIdentifier(WoodType $treeType) : BID{
|
||||
return new BID(match($treeType){
|
||||
WoodType::OAK => Ids::OAK_BUTTON,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_BUTTON,
|
||||
WoodType::BIRCH => Ids::BIRCH_BUTTON,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_BUTTON,
|
||||
WoodType::ACACIA => Ids::ACACIA_BUTTON,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_BUTTON,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_BUTTON,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_BUTTON,
|
||||
WoodType::WARPED => Ids::WARPED_BUTTON,
|
||||
WoodType::CHERRY => Ids::CHERRY_BUTTON,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getPressurePlateIdentifier(WoodType $treeType) : BID{
|
||||
return new BID(match($treeType){
|
||||
WoodType::OAK => Ids::OAK_PRESSURE_PLATE,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_PRESSURE_PLATE,
|
||||
WoodType::BIRCH => Ids::BIRCH_PRESSURE_PLATE,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_PRESSURE_PLATE,
|
||||
WoodType::ACACIA => Ids::ACACIA_PRESSURE_PLATE,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_PRESSURE_PLATE,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_PRESSURE_PLATE,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_PRESSURE_PLATE,
|
||||
WoodType::WARPED => Ids::WARPED_PRESSURE_PLATE,
|
||||
WoodType::CHERRY => Ids::CHERRY_PRESSURE_PLATE,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getDoorIdentifier(WoodType $treeType) : BID{
|
||||
return new BID(match($treeType){
|
||||
WoodType::OAK => Ids::OAK_DOOR,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_DOOR,
|
||||
WoodType::BIRCH => Ids::BIRCH_DOOR,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_DOOR,
|
||||
WoodType::ACACIA => Ids::ACACIA_DOOR,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_DOOR,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_DOOR,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_DOOR,
|
||||
WoodType::WARPED => Ids::WARPED_DOOR,
|
||||
WoodType::CHERRY => Ids::CHERRY_DOOR,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getFenceGateIdentifier(WoodType $treeType) : BID{
|
||||
return new BID(match($treeType){
|
||||
WoodType::OAK => Ids::OAK_FENCE_GATE,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_FENCE_GATE,
|
||||
WoodType::BIRCH => Ids::BIRCH_FENCE_GATE,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_FENCE_GATE,
|
||||
WoodType::ACACIA => Ids::ACACIA_FENCE_GATE,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_FENCE_GATE,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_FENCE_GATE,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_FENCE_GATE,
|
||||
WoodType::WARPED => Ids::WARPED_FENCE_GATE,
|
||||
WoodType::CHERRY => Ids::CHERRY_FENCE_GATE,
|
||||
});
|
||||
}
|
||||
|
||||
public static function getStairsIdentifier(WoodType $treeType) : BID{
|
||||
return new BID(match($treeType){
|
||||
WoodType::OAK => Ids::OAK_STAIRS,
|
||||
WoodType::SPRUCE => Ids::SPRUCE_STAIRS,
|
||||
WoodType::BIRCH => Ids::BIRCH_STAIRS,
|
||||
WoodType::JUNGLE => Ids::JUNGLE_STAIRS,
|
||||
WoodType::ACACIA => Ids::ACACIA_STAIRS,
|
||||
WoodType::DARK_OAK => Ids::DARK_OAK_STAIRS,
|
||||
WoodType::MANGROVE => Ids::MANGROVE_STAIRS,
|
||||
WoodType::CRIMSON => Ids::CRIMSON_STAIRS,
|
||||
WoodType::WARPED => Ids::WARPED_STAIRS,
|
||||
WoodType::CHERRY => Ids::CHERRY_STAIRS,
|
||||
});
|
||||
}
|
||||
}
|
40
src/block/inventory/CampfireInventory.php
Normal file
40
src/block/inventory/CampfireInventory.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?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\inventory;
|
||||
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
class CampfireInventory extends SimpleInventory implements BlockInventory{
|
||||
use BlockInventoryTrait;
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(4);
|
||||
}
|
||||
|
||||
public function getMaxStackSize() : int{
|
||||
return 1;
|
||||
}
|
||||
}
|
@ -39,7 +39,10 @@ class EnchantInventory extends SimpleInventory implements BlockInventory, Tempor
|
||||
public const SLOT_INPUT = 0;
|
||||
public const SLOT_LAPIS = 1;
|
||||
|
||||
/** @var EnchantingOption[] $options */
|
||||
/**
|
||||
* @var EnchantingOption[] $options
|
||||
* @phpstan-var list<EnchantingOption>
|
||||
*/
|
||||
private array $options = [];
|
||||
|
||||
public function __construct(Position $holder){
|
||||
|
143
src/block/tile/Campfire.php
Normal file
143
src/block/tile/Campfire.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\block\Campfire as BlockCampfire;
|
||||
use pocketmine\block\inventory\CampfireInventory;
|
||||
use pocketmine\inventory\CallbackInventoryListener;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\network\mcpe\convert\TypeConverter;
|
||||
use pocketmine\world\World;
|
||||
|
||||
class Campfire extends Spawnable implements Container{
|
||||
use ContainerTrait;
|
||||
|
||||
private const TAG_FIRST_INPUT_ITEM = "Item1"; //TAG_Compound
|
||||
private const TAG_SECOND_INPUT_ITEM = "Item2"; //TAG_Compound
|
||||
private const TAG_THIRD_INPUT_ITEM = "Item3"; //TAG_Compound
|
||||
private const TAG_FOURTH_INPUT_ITEM = "Item4"; //TAG_Compound
|
||||
|
||||
private const TAG_FIRST_COOKING_TIME = "ItemTime1"; //TAG_Int
|
||||
private const TAG_SECOND_COOKING_TIME = "ItemTime2"; //TAG_Int
|
||||
private const TAG_THIRD_COOKING_TIME = "ItemTime3"; //TAG_Int
|
||||
private const TAG_FOURTH_COOKING_TIME = "ItemTime4"; //TAG_Int
|
||||
|
||||
protected CampfireInventory $inventory;
|
||||
/** @var array<int, int> */
|
||||
private array $cookingTimes = [];
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
parent::__construct($world, $pos);
|
||||
$this->inventory = new CampfireInventory($this->position);
|
||||
$this->inventory->getListeners()->add(CallbackInventoryListener::onAnyChange(
|
||||
static function(Inventory $unused) use ($world, $pos) : void{
|
||||
$block = $world->getBlock($pos);
|
||||
if($block instanceof BlockCampfire){
|
||||
$world->setBlock($pos, $block);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public function getInventory() : CampfireInventory{
|
||||
return $this->inventory;
|
||||
}
|
||||
|
||||
public function getRealInventory() : CampfireInventory{
|
||||
return $this->inventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
* @phpstan-return array<int, int>
|
||||
*/
|
||||
public function getCookingTimes() : array{
|
||||
return $this->cookingTimes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $cookingTimes
|
||||
* @phpstan-param array<int, int> $cookingTimes
|
||||
*/
|
||||
public function setCookingTimes(array $cookingTimes) : void{
|
||||
$this->cookingTimes = $cookingTimes;
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
$items = [];
|
||||
$listeners = $this->inventory->getListeners()->toArray();
|
||||
$this->inventory->getListeners()->remove(...$listeners); //prevent any events being fired by initialization
|
||||
|
||||
foreach([
|
||||
[0, self::TAG_FIRST_INPUT_ITEM, self::TAG_FIRST_COOKING_TIME],
|
||||
[1, self::TAG_SECOND_INPUT_ITEM, self::TAG_SECOND_COOKING_TIME],
|
||||
[2, self::TAG_THIRD_INPUT_ITEM, self::TAG_THIRD_COOKING_TIME],
|
||||
[3, self::TAG_FOURTH_INPUT_ITEM, self::TAG_FOURTH_COOKING_TIME],
|
||||
] as [$slot, $itemTag, $cookingTimeTag]){
|
||||
if(($tag = $nbt->getTag($itemTag)) instanceof CompoundTag){
|
||||
$items[$slot] = Item::nbtDeserialize($tag);
|
||||
}
|
||||
if(($tag = $nbt->getTag($cookingTimeTag)) instanceof IntTag){
|
||||
$this->cookingTimes[$slot] = $tag->getValue();
|
||||
}
|
||||
}
|
||||
$this->inventory->setContents($items);
|
||||
$this->inventory->getListeners()->add(...$listeners);
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
foreach([
|
||||
[0, self::TAG_FIRST_INPUT_ITEM, self::TAG_FIRST_COOKING_TIME],
|
||||
[1, self::TAG_SECOND_INPUT_ITEM, self::TAG_SECOND_COOKING_TIME],
|
||||
[2, self::TAG_THIRD_INPUT_ITEM, self::TAG_THIRD_COOKING_TIME],
|
||||
[3, self::TAG_FOURTH_INPUT_ITEM, self::TAG_FOURTH_COOKING_TIME],
|
||||
] as [$slot, $itemTag, $cookingTimeTag]){
|
||||
$item = $this->inventory->getItem($slot);
|
||||
if(!$item->isNull()){
|
||||
$nbt->setTag($itemTag, $item->nbtSerialize());
|
||||
if(isset($this->cookingTimes[$slot])){
|
||||
$nbt->setInt($cookingTimeTag, $this->cookingTimes[$slot]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
foreach([
|
||||
0 => self::TAG_FIRST_INPUT_ITEM,
|
||||
1 => self::TAG_SECOND_INPUT_ITEM,
|
||||
2 => self::TAG_THIRD_INPUT_ITEM,
|
||||
3 => self::TAG_FOURTH_INPUT_ITEM
|
||||
] as $slot => $tag){
|
||||
$item = $this->inventory->getItem($slot);
|
||||
if(!$item->isNull()){
|
||||
$nbt->setTag($tag, TypeConverter::getInstance()->getItemTranslator()->toNetworkNbt($item));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -40,8 +40,12 @@ use function count;
|
||||
class ChiseledBookshelf extends Tile implements Container{
|
||||
use ContainerTrait;
|
||||
|
||||
private const TAG_LAST_INTERACTED_SLOT = "LastInteractedSlot"; //TAG_Int
|
||||
|
||||
private SimpleInventory $inventory;
|
||||
|
||||
private ?ChiseledBookshelfSlot $lastInteractedSlot = null;
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
parent::__construct($world, $pos);
|
||||
$this->inventory = new SimpleInventory(count(ChiseledBookshelfSlot::cases()));
|
||||
@ -55,12 +59,30 @@ class ChiseledBookshelf extends Tile implements Container{
|
||||
return $this->inventory;
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
$this->loadItems($nbt);
|
||||
public function getLastInteractedSlot() : ?ChiseledBookshelfSlot{
|
||||
return $this->lastInteractedSlot;
|
||||
}
|
||||
|
||||
public function writeSaveData(CompoundTag $nbt) : void{
|
||||
public function setLastInteractedSlot(?ChiseledBookshelfSlot $lastInteractedSlot) : void{
|
||||
$this->lastInteractedSlot = $lastInteractedSlot;
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
$this->loadItems($nbt);
|
||||
|
||||
$lastInteractedSlot = $nbt->getInt(self::TAG_LAST_INTERACTED_SLOT, 0);
|
||||
if($lastInteractedSlot !== 0){
|
||||
$this->lastInteractedSlot = ChiseledBookshelfSlot::tryFrom($lastInteractedSlot - 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$this->saveItems($nbt);
|
||||
|
||||
$nbt->setInt(self::TAG_LAST_INTERACTED_SLOT, $this->lastInteractedSlot !== null ?
|
||||
$this->lastInteractedSlot->value + 1 :
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
protected function loadItems(CompoundTag $tag) : void{
|
||||
|
@ -57,6 +57,7 @@ final class TileFactory{
|
||||
$this->register(Bell::class, ["Bell", "minecraft:bell"]);
|
||||
$this->register(BlastFurnace::class, ["BlastFurnace", "minecraft:blast_furnace"]);
|
||||
$this->register(BrewingStand::class, ["BrewingStand", "minecraft:brewing_stand"]);
|
||||
$this->register(Campfire::class, ["Campfire", "minecraft:campfire"]);
|
||||
$this->register(Cauldron::class, ["Cauldron", "minecraft:cauldron"]);
|
||||
$this->register(Chest::class, ["Chest", "minecraft:chest"]);
|
||||
$this->register(ChiseledBookshelf::class, ["ChiseledBookshelf", "minecraft:chiseled_bookshelf"]);
|
||||
@ -79,7 +80,6 @@ final class TileFactory{
|
||||
$this->register(MobHead::class, ["Skull", "minecraft:skull"]);
|
||||
$this->register(GlowingItemFrame::class, ["GlowItemFrame"]);
|
||||
|
||||
//TODO: Campfire
|
||||
//TODO: ChalkboardBlock
|
||||
//TODO: ChemistryTable
|
||||
//TODO: CommandBlock
|
||||
|
@ -81,10 +81,12 @@ enum BannerPatternType{
|
||||
case DIAGONAL_RIGHT;
|
||||
case DIAGONAL_UP_LEFT;
|
||||
case DIAGONAL_UP_RIGHT;
|
||||
case FLOW;
|
||||
case FLOWER;
|
||||
case GLOBE;
|
||||
case GRADIENT;
|
||||
case GRADIENT_UP;
|
||||
case GUSTER;
|
||||
case HALF_HORIZONTAL;
|
||||
case HALF_HORIZONTAL_BOTTOM;
|
||||
case HALF_VERTICAL;
|
||||
|
38
src/block/utils/CopperMaterial.php
Normal file
38
src/block/utils/CopperMaterial.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Represents copper blocks that have oxidized and waxed variations.
|
||||
*/
|
||||
interface CopperMaterial{
|
||||
|
||||
public function getOxidation() : CopperOxidation;
|
||||
|
||||
public function setOxidation(CopperOxidation $oxidation) : CopperMaterial;
|
||||
|
||||
public function isWaxed() : bool;
|
||||
|
||||
public function setWaxed(bool $waxed) : CopperMaterial;
|
||||
}
|
72
src/block/utils/MultiAnyFacingTrait.php
Normal file
72
src/block/utils/MultiAnyFacingTrait.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?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;
|
||||
use pocketmine\math\Facing;
|
||||
|
||||
/**
|
||||
* Used by blocks that can have multiple target faces in the area of one solid block, such as covering three sides of a corner.
|
||||
*/
|
||||
trait MultiAnyFacingTrait{
|
||||
|
||||
/** @var int[] */
|
||||
protected array $faces = [];
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->facingFlags($this->faces);
|
||||
}
|
||||
|
||||
/** @return int[] */
|
||||
public function getFaces() : array{ return $this->faces; }
|
||||
|
||||
public function hasFace(int $face) : bool{
|
||||
return isset($this->faces[$face]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $faces
|
||||
* @return $this
|
||||
*/
|
||||
public function setFaces(array $faces) : self{
|
||||
$uniqueFaces = [];
|
||||
foreach($faces as $face){
|
||||
Facing::validate($face);
|
||||
$uniqueFaces[$face] = $face;
|
||||
}
|
||||
$this->faces = $uniqueFaces;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function setFace(int $face, bool $value) : self{
|
||||
Facing::validate($face);
|
||||
if($value){
|
||||
$this->faces[$face] = $face;
|
||||
}else{
|
||||
unset($this->faces[$face]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
96
src/block/utils/MultiAnySupportTrait.php
Normal file
96
src/block/utils/MultiAnySupportTrait.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?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\block\Block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function array_key_first;
|
||||
use function count;
|
||||
|
||||
/**
|
||||
* Used by blocks that have multiple support requirements in the area of one solid block, such as covering three sides of a corner.
|
||||
* Prevents placement if support isn't available and automatically destroys a block side if it's support is removed.
|
||||
*/
|
||||
trait MultiAnySupportTrait{
|
||||
use MultiAnyFacingTrait;
|
||||
|
||||
/**
|
||||
* Returns a list of faces that block should already have when placed.
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
abstract protected function getInitialPlaceFaces(Block $blockReplace) : array;
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
$this->faces = $this->getInitialPlaceFaces($blockReplace);
|
||||
$availableFaces = $this->getAvailableFaces();
|
||||
|
||||
if(count($availableFaces) === 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
$opposite = Facing::opposite($face);
|
||||
$placedFace = isset($availableFaces[$opposite]) ? $opposite : array_key_first($availableFaces);
|
||||
$this->faces[$placedFace] = $placedFace;
|
||||
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$changed = false;
|
||||
|
||||
foreach($this->faces as $face){
|
||||
if($this->getAdjacentSupportType($face) !== SupportType::FULL){
|
||||
unset($this->faces[$face]);
|
||||
$changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if($changed){
|
||||
$world = $this->position->getWorld();
|
||||
if(count($this->faces) === 0){
|
||||
$world->useBreakOn($this->position);
|
||||
}else{
|
||||
$world->setBlock($this->position, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, int> $faces
|
||||
*/
|
||||
private function getAvailableFaces() : array{
|
||||
$faces = [];
|
||||
foreach(Facing::ALL as $face){
|
||||
if(!$this->hasFace($face) && $this->getAdjacentSupportType($face) === SupportType::FULL){
|
||||
$faces[$face] = $face;
|
||||
}
|
||||
}
|
||||
return $faces;
|
||||
}
|
||||
}
|
@ -36,13 +36,17 @@ use function str_contains;
|
||||
class SignText{
|
||||
public const LINE_COUNT = 4;
|
||||
|
||||
/** @var string[] */
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var array{0: string, 1: string, 2: string, 3: string}
|
||||
*/
|
||||
private array $lines;
|
||||
private Color $baseColor;
|
||||
private bool $glowing;
|
||||
|
||||
/**
|
||||
* @param string[]|null $lines index-sensitive; keys 0-3 will be used, regardless of array order
|
||||
* @phpstan-param array{0?: string, 1?: string, 2?: string, 3?: string}|null $lines
|
||||
*
|
||||
* @throws \InvalidArgumentException if the array size is greater than 4
|
||||
* @throws \InvalidArgumentException if invalid keys (out of bounds or string) are found in the array
|
||||
@ -82,6 +86,7 @@ class SignText{
|
||||
* Returns an array of lines currently on the sign.
|
||||
*
|
||||
* @return string[]
|
||||
* @phpstan-return array{0: string, 1: string, 2: string, 3: string}
|
||||
*/
|
||||
public function getLines() : array{
|
||||
return $this->lines;
|
||||
|
60
src/command/ClosureCommand.php
Normal file
60
src/command/ClosureCommand.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?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\command;
|
||||
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
/**
|
||||
* @phpstan-type Execute \Closure(CommandSender $sender, Command $command, string $commandLabel, list<string> $args) : mixed
|
||||
*/
|
||||
final class ClosureCommand extends Command{
|
||||
/** @phpstan-var Execute */
|
||||
private \Closure $execute;
|
||||
|
||||
/**
|
||||
* @param string[] $permissions
|
||||
* @phpstan-param Execute $execute
|
||||
*/
|
||||
public function __construct(
|
||||
string $name,
|
||||
\Closure $execute,
|
||||
array $permissions,
|
||||
Translatable|string $description = "",
|
||||
Translatable|string|null $usageMessage = null,
|
||||
array $aliases = []
|
||||
){
|
||||
Utils::validateCallableSignature(
|
||||
fn(CommandSender $sender, Command $command, string $commandLabel, array $args) : mixed => 1,
|
||||
$execute,
|
||||
);
|
||||
$this->execute = $execute;
|
||||
parent::__construct($name, $description, $usageMessage, $aliases);
|
||||
$this->setPermissions($permissions);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
return ($this->execute)($sender, $this, $commandLabel, $args);
|
||||
}
|
||||
}
|
@ -44,10 +44,16 @@ abstract class Command{
|
||||
private string $nextLabel;
|
||||
private string $label;
|
||||
|
||||
/** @var string[] */
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
private array $aliases = [];
|
||||
|
||||
/** @var string[] */
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
private array $activeAliases = [];
|
||||
|
||||
private ?CommandMap $commandMap = null;
|
||||
@ -62,6 +68,7 @@ abstract class Command{
|
||||
|
||||
/**
|
||||
* @param string[] $aliases
|
||||
* @phpstan-param list<string> $aliases
|
||||
*/
|
||||
public function __construct(string $name, Translatable|string $description = "", Translatable|string|null $usageMessage = null, array $aliases = []){
|
||||
$this->name = $name;
|
||||
@ -182,6 +189,7 @@ abstract class Command{
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
public function getAliases() : array{
|
||||
return $this->activeAliases;
|
||||
@ -201,6 +209,7 @@ abstract class Command{
|
||||
|
||||
/**
|
||||
* @param string[] $aliases
|
||||
* @phpstan-param list<string> $aliases
|
||||
*/
|
||||
public function setAliases(array $aliases) : void{
|
||||
$this->aliases = $aliases;
|
||||
|
@ -64,12 +64,14 @@ use pocketmine\command\defaults\TransferServerCommand;
|
||||
use pocketmine\command\defaults\VanillaCommand;
|
||||
use pocketmine\command\defaults\VersionCommand;
|
||||
use pocketmine\command\defaults\WhitelistCommand;
|
||||
use pocketmine\command\defaults\XpCommand;
|
||||
use pocketmine\command\utils\CommandStringHelper;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
@ -80,7 +82,10 @@ use function trim;
|
||||
|
||||
class SimpleCommandMap implements CommandMap{
|
||||
|
||||
/** @var Command[] */
|
||||
/**
|
||||
* @var Command[]
|
||||
* @phpstan-var array<string, Command>
|
||||
*/
|
||||
protected array $knownCommands = [];
|
||||
|
||||
public function __construct(private Server $server){
|
||||
@ -128,7 +133,8 @@ class SimpleCommandMap implements CommandMap{
|
||||
new TitleCommand(),
|
||||
new TransferServerCommand(),
|
||||
new VersionCommand(),
|
||||
new WhitelistCommand()
|
||||
new WhitelistCommand(),
|
||||
new XpCommand(),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -169,7 +175,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
}
|
||||
|
||||
public function unregister(Command $command) : bool{
|
||||
foreach($this->knownCommands as $lbl => $cmd){
|
||||
foreach(Utils::promoteKeys($this->knownCommands) as $lbl => $cmd){
|
||||
if($cmd === $command){
|
||||
unset($this->knownCommands[$lbl]);
|
||||
}
|
||||
@ -237,6 +243,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
|
||||
/**
|
||||
* @return Command[]
|
||||
* @phpstan-return array<string, Command>
|
||||
*/
|
||||
public function getCommands() : array{
|
||||
return $this->knownCommands;
|
||||
@ -245,7 +252,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
public function registerServerAliases() : void{
|
||||
$values = $this->server->getCommandAliases();
|
||||
|
||||
foreach($values as $alias => $commandStrings){
|
||||
foreach(Utils::stringifyKeys($values) as $alias => $commandStrings){
|
||||
if(str_contains($alias, ":")){
|
||||
$this->server->getLogger()->warning($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_command_alias_illegal($alias)));
|
||||
continue;
|
||||
|
@ -26,28 +26,28 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\scheduler\BulkCurlTask;
|
||||
use pocketmine\scheduler\BulkCurlTaskOperation;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\InternetException;
|
||||
use pocketmine\utils\InternetRequestResult;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function count;
|
||||
use function fclose;
|
||||
use function file_exists;
|
||||
use function fopen;
|
||||
use function fseek;
|
||||
use function fwrite;
|
||||
use function http_build_query;
|
||||
use function implode;
|
||||
use function is_array;
|
||||
use function json_decode;
|
||||
use function mkdir;
|
||||
use function stream_get_contents;
|
||||
use function strtolower;
|
||||
use const CURLOPT_AUTOREFERER;
|
||||
use const CURLOPT_FOLLOWLOCATION;
|
||||
@ -101,82 +101,91 @@ class TimingsCommand extends VanillaCommand{
|
||||
TimingsHandler::reload();
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_reset());
|
||||
}elseif($mode === "merged" || $mode === "report" || $paste){
|
||||
$timings = "";
|
||||
if($paste){
|
||||
$fileTimings = Utils::assumeNotFalse(fopen("php://temp", "r+b"), "Opening php://temp should never fail");
|
||||
}else{
|
||||
$index = 0;
|
||||
$timingFolder = Path::join($sender->getServer()->getDataPath(), "timings");
|
||||
|
||||
if(!file_exists($timingFolder)){
|
||||
mkdir($timingFolder, 0777);
|
||||
}
|
||||
$timings = Path::join($timingFolder, "timings.txt");
|
||||
while(file_exists($timings)){
|
||||
$timings = Path::join($timingFolder, "timings" . (++$index) . ".txt");
|
||||
}
|
||||
|
||||
$fileTimings = fopen($timings, "a+b");
|
||||
}
|
||||
$lines = TimingsHandler::printTimings();
|
||||
foreach($lines as $line){
|
||||
fwrite($fileTimings, $line . PHP_EOL);
|
||||
}
|
||||
|
||||
if($paste){
|
||||
fseek($fileTimings, 0);
|
||||
$data = [
|
||||
"browser" => $agent = $sender->getServer()->getName() . " " . $sender->getServer()->getPocketMineVersion(),
|
||||
"data" => $content = stream_get_contents($fileTimings)
|
||||
];
|
||||
fclose($fileTimings);
|
||||
|
||||
$host = $sender->getServer()->getConfigGroup()->getPropertyString(YmlServerProperties::TIMINGS_HOST, "timings.pmmp.io");
|
||||
|
||||
$sender->getServer()->getAsyncPool()->submitTask(new BulkCurlTask(
|
||||
[new BulkCurlTaskOperation(
|
||||
"https://$host?upload=true",
|
||||
10,
|
||||
[],
|
||||
[
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"User-Agent: $agent",
|
||||
"Content-Type: application/x-www-form-urlencoded"
|
||||
],
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query($data),
|
||||
CURLOPT_AUTOREFERER => false,
|
||||
CURLOPT_FOLLOWLOCATION => false
|
||||
]
|
||||
)],
|
||||
function(array $results) use ($sender, $host) : void{
|
||||
/** @phpstan-var array<InternetRequestResult|InternetException> $results */
|
||||
if($sender instanceof Player && !$sender->isOnline()){ // TODO replace with a more generic API method for checking availability of CommandSender
|
||||
return;
|
||||
}
|
||||
$result = $results[0];
|
||||
if($result instanceof InternetException){
|
||||
$sender->getServer()->getLogger()->logException($result);
|
||||
return;
|
||||
}
|
||||
$response = json_decode($result->getBody(), true);
|
||||
if(is_array($response) && isset($response["id"])){
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsRead(
|
||||
"https://" . $host . "/?id=" . $response["id"]));
|
||||
}else{
|
||||
$sender->getServer()->getLogger()->debug("Invalid response from timings server (" . $result->getCode() . "): " . $result->getBody());
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_pasteError());
|
||||
}
|
||||
}
|
||||
));
|
||||
}else{
|
||||
fclose($fileTimings);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsWrite($timings));
|
||||
}
|
||||
$timingsPromise = TimingsHandler::requestPrintTimings();
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_collect());
|
||||
$timingsPromise->onCompletion(
|
||||
fn(array $lines) => $paste ? $this->uploadReport($lines, $sender) : $this->createReportFile($lines, $sender),
|
||||
fn() => throw new AssumptionFailedError("This promise is not expected to be rejected")
|
||||
);
|
||||
}else{
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $lines
|
||||
* @phpstan-param list<string> $lines
|
||||
*/
|
||||
private function createReportFile(array $lines, CommandSender $sender) : void{
|
||||
$index = 0;
|
||||
$timingFolder = Path::join($sender->getServer()->getDataPath(), "timings");
|
||||
|
||||
if(!file_exists($timingFolder)){
|
||||
mkdir($timingFolder, 0777);
|
||||
}
|
||||
$timings = Path::join($timingFolder, "timings.txt");
|
||||
while(file_exists($timings)){
|
||||
$timings = Path::join($timingFolder, "timings" . (++$index) . ".txt");
|
||||
}
|
||||
|
||||
$fileTimings = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen($timings, "a+b"));
|
||||
foreach($lines as $line){
|
||||
fwrite($fileTimings, $line . PHP_EOL);
|
||||
}
|
||||
fclose($fileTimings);
|
||||
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsWrite($timings));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $lines
|
||||
* @phpstan-param list<string> $lines
|
||||
*/
|
||||
private function uploadReport(array $lines, CommandSender $sender) : void{
|
||||
$data = [
|
||||
"browser" => $agent = $sender->getServer()->getName() . " " . $sender->getServer()->getPocketMineVersion(),
|
||||
"data" => implode("\n", $lines)
|
||||
];
|
||||
|
||||
$host = $sender->getServer()->getConfigGroup()->getPropertyString(YmlServerProperties::TIMINGS_HOST, "timings.pmmp.io");
|
||||
|
||||
$sender->getServer()->getAsyncPool()->submitTask(new BulkCurlTask(
|
||||
[new BulkCurlTaskOperation(
|
||||
"https://$host?upload=true",
|
||||
10,
|
||||
[],
|
||||
[
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"User-Agent: $agent",
|
||||
"Content-Type: application/x-www-form-urlencoded"
|
||||
],
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query($data),
|
||||
CURLOPT_AUTOREFERER => false,
|
||||
CURLOPT_FOLLOWLOCATION => false
|
||||
]
|
||||
)],
|
||||
function(array $results) use ($sender, $host) : void{
|
||||
/** @phpstan-var array<InternetRequestResult|InternetException> $results */
|
||||
if($sender instanceof Player && !$sender->isOnline()){ // TODO replace with a more generic API method for checking availability of CommandSender
|
||||
return;
|
||||
}
|
||||
$result = $results[0];
|
||||
if($result instanceof InternetException){
|
||||
$sender->getServer()->getLogger()->logException($result);
|
||||
return;
|
||||
}
|
||||
$response = json_decode($result->getBody(), true);
|
||||
if(is_array($response) && isset($response["id"])){
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsRead(
|
||||
"https://" . $host . "/?id=" . $response["id"]));
|
||||
}else{
|
||||
$sender->getServer()->getLogger()->debug("Invalid response from timings server (" . $result->getCode() . "): " . $result->getBody());
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_pasteError());
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
89
src/command/defaults/XpCommand.php
Normal file
89
src/command/defaults/XpCommand.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?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\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\entity\Attribute;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Limits;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function abs;
|
||||
use function count;
|
||||
use function str_ends_with;
|
||||
use function substr;
|
||||
|
||||
class XpCommand extends VanillaCommand{
|
||||
|
||||
public function __construct(){
|
||||
parent::__construct(
|
||||
"xp",
|
||||
KnownTranslationFactory::pocketmine_command_xp_description(),
|
||||
KnownTranslationFactory::pocketmine_command_xp_usage()
|
||||
);
|
||||
$this->setPermissions([
|
||||
DefaultPermissionNames::COMMAND_XP_SELF,
|
||||
DefaultPermissionNames::COMMAND_XP_OTHER
|
||||
]);
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, string $commandLabel, array $args){
|
||||
if(count($args) < 1){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player = $this->fetchPermittedPlayerTarget($sender, $args[1] ?? null, DefaultPermissionNames::COMMAND_XP_SELF, DefaultPermissionNames::COMMAND_XP_OTHER);
|
||||
if($player === null){
|
||||
return true;
|
||||
}
|
||||
|
||||
$xpManager = $player->getXpManager();
|
||||
if(str_ends_with($args[0], "L")){
|
||||
$xpLevelAttr = $player->getAttributeMap()->get(Attribute::EXPERIENCE_LEVEL) ?? throw new AssumptionFailedError();
|
||||
$maxXpLevel = (int) $xpLevelAttr->getMaxValue();
|
||||
$currentXpLevel = $xpManager->getXpLevel();
|
||||
$xpLevels = $this->getInteger($sender, substr($args[0], 0, -1), -$currentXpLevel, $maxXpLevel - $currentXpLevel);
|
||||
if($xpLevels >= 0){
|
||||
$xpManager->addXpLevels($xpLevels, false);
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_xp_success_levels((string) $xpLevels, $player->getName()));
|
||||
}else{
|
||||
$xpLevels = abs($xpLevels);
|
||||
$xpManager->subtractXpLevels($xpLevels);
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_xp_success_negative_levels((string) $xpLevels, $player->getName()));
|
||||
}
|
||||
}else{
|
||||
$xp = $this->getInteger($sender, $args[0], max: Limits::INT32_MAX);
|
||||
if($xp < 0){
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_xp_failure_widthdrawXp()->prefix(TextFormat::RED));
|
||||
}else{
|
||||
$xpManager->addXp($xp, false);
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_xp_success((string) $xp, $player->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -29,23 +29,21 @@ use pocketmine\utils\Process;
|
||||
use function cli_set_process_title;
|
||||
use function count;
|
||||
use function dirname;
|
||||
use function feof;
|
||||
use function fwrite;
|
||||
use function stream_socket_client;
|
||||
use function is_numeric;
|
||||
use const PHP_EOL;
|
||||
use const STDOUT;
|
||||
|
||||
if(count($argv) !== 2 || !is_numeric($argv[1])){
|
||||
echo "Usage: " . $argv[0] . " <command token seed>" . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$commandTokenSeed = (int) $argv[1];
|
||||
|
||||
require dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||
|
||||
if(count($argv) !== 2){
|
||||
die("Please provide a server to connect to");
|
||||
}
|
||||
|
||||
@cli_set_process_title('PocketMine-MP Console Reader');
|
||||
$errCode = null;
|
||||
$errMessage = null;
|
||||
$socket = stream_socket_client($argv[1], $errCode, $errMessage, 15.0);
|
||||
if($socket === false){
|
||||
throw new \RuntimeException("Failed to connect to server process ($errCode): $errMessage");
|
||||
}
|
||||
|
||||
/** @phpstan-var ThreadSafeArray<int, string> $channel */
|
||||
$channel = new ThreadSafeArray();
|
||||
@ -75,15 +73,15 @@ $thread = new class($channel) extends NativeThread{
|
||||
};
|
||||
|
||||
$thread->start(NativeThread::INHERIT_NONE);
|
||||
while(!feof($socket)){
|
||||
while(true){
|
||||
$line = $channel->synchronized(function() use ($channel) : ?string{
|
||||
if(count($channel) === 0){
|
||||
$channel->wait(1_000_000);
|
||||
}
|
||||
$line = $channel->shift();
|
||||
return $line;
|
||||
return $channel->shift();
|
||||
});
|
||||
if(@fwrite($socket, ($line ?? "") . "\n") === false){
|
||||
$message = $line !== null ? ConsoleReaderChildProcessUtils::createMessage($line, $commandTokenSeed) : "";
|
||||
if(@fwrite(STDOUT, $message . "\n") === false){
|
||||
//Always send even if there's no line, to check if the parent is alive
|
||||
//If the parent process was terminated forcibly, it won't close the connection properly, so feof() will return
|
||||
//false even though the connection is actually broken. However, fwrite() will fail.
|
||||
|
@ -29,19 +29,16 @@ use Symfony\Component\Filesystem\Path;
|
||||
use function base64_encode;
|
||||
use function fgets;
|
||||
use function fopen;
|
||||
use function mt_rand;
|
||||
use function preg_replace;
|
||||
use function proc_close;
|
||||
use function proc_open;
|
||||
use function proc_terminate;
|
||||
use function rtrim;
|
||||
use function sprintf;
|
||||
use function stream_select;
|
||||
use function stream_socket_accept;
|
||||
use function stream_socket_get_name;
|
||||
use function stream_socket_server;
|
||||
use function stream_socket_shutdown;
|
||||
use function trim;
|
||||
use const PHP_BINARY;
|
||||
use const STREAM_SHUT_RDWR;
|
||||
|
||||
/**
|
||||
* This pile of shit exists because PHP on Windows is broken, and can't handle stream_select() on stdin or pipes
|
||||
@ -58,44 +55,44 @@ use const STREAM_SHUT_RDWR;
|
||||
* communication.
|
||||
*/
|
||||
final class ConsoleReaderChildProcessDaemon{
|
||||
public const TOKEN_DELIMITER = ":";
|
||||
public const TOKEN_HASH_ALGO = "xxh3";
|
||||
|
||||
private \PrefixedLogger $logger;
|
||||
/** @var resource */
|
||||
private $subprocess;
|
||||
/** @var resource */
|
||||
private $socket;
|
||||
private int $commandTokenSeed;
|
||||
|
||||
public function __construct(
|
||||
\Logger $logger
|
||||
){
|
||||
$this->logger = new \PrefixedLogger($logger, "Console Reader Daemon");
|
||||
$this->commandTokenSeed = mt_rand();
|
||||
$this->prepareSubprocess();
|
||||
}
|
||||
|
||||
private function prepareSubprocess() : void{
|
||||
$server = stream_socket_server("tcp://127.0.0.1:0");
|
||||
if($server === false){
|
||||
throw new \RuntimeException("Failed to open console reader socket server");
|
||||
}
|
||||
$address = Utils::assumeNotFalse(stream_socket_get_name($server, false), "stream_socket_get_name() shouldn't return false here");
|
||||
|
||||
//Windows sucks, and likes to corrupt UTF-8 file paths when they travel to the subprocess, so we base64 encode
|
||||
//the path to avoid the problem. This is an abysmally shitty hack, but here we are :(
|
||||
$sub = Utils::assumeNotFalse(proc_open(
|
||||
[PHP_BINARY, '-dopcache.enable_cli=0', '-r', sprintf('require base64_decode("%s", true);', base64_encode(Path::join(__DIR__, 'ConsoleReaderChildProcess.php'))), $address],
|
||||
[
|
||||
PHP_BINARY,
|
||||
'-dopcache.enable_cli=0',
|
||||
'-r',
|
||||
sprintf('require base64_decode("%s", true);', base64_encode(Path::join(__DIR__, 'ConsoleReaderChildProcess.php'))),
|
||||
(string) $this->commandTokenSeed
|
||||
],
|
||||
[
|
||||
1 => ['socket'],
|
||||
2 => fopen("php://stderr", "w"),
|
||||
],
|
||||
$pipes
|
||||
), "Something has gone horribly wrong");
|
||||
|
||||
$client = stream_socket_accept($server, 15);
|
||||
if($client === false){
|
||||
throw new AssumptionFailedError("stream_socket_accept() returned false");
|
||||
}
|
||||
stream_socket_shutdown($server, STREAM_SHUT_RDWR);
|
||||
|
||||
$this->subprocess = $sub;
|
||||
$this->socket = $client;
|
||||
$this->socket = $pipes[1];
|
||||
}
|
||||
|
||||
private function shutdownSubprocess() : void{
|
||||
@ -104,7 +101,6 @@ final class ConsoleReaderChildProcessDaemon{
|
||||
//the first place).
|
||||
proc_terminate($this->subprocess);
|
||||
proc_close($this->subprocess);
|
||||
stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
|
||||
}
|
||||
|
||||
public function readLine() : ?string{
|
||||
@ -112,13 +108,27 @@ final class ConsoleReaderChildProcessDaemon{
|
||||
$w = null;
|
||||
$e = null;
|
||||
if(stream_select($r, $w, $e, 0, 0) === 1){
|
||||
$command = fgets($this->socket);
|
||||
if($command === false){
|
||||
$line = fgets($this->socket);
|
||||
if($line === false){
|
||||
$this->logger->debug("Lost connection to subprocess, restarting (maybe the child process was killed from outside?)");
|
||||
$this->shutdownSubprocess();
|
||||
$this->prepareSubprocess();
|
||||
return null;
|
||||
}
|
||||
$line = rtrim($line, "\n");
|
||||
|
||||
if($line === ""){
|
||||
//keepalive
|
||||
return null;
|
||||
}
|
||||
|
||||
$command = ConsoleReaderChildProcessUtils::parseMessage($line, $this->commandTokenSeed);
|
||||
if($command === null){
|
||||
//this is not a command - it may be some kind of error output from the subprocess
|
||||
//write it directly to the console
|
||||
$this->logger->warning("Unexpected output from child process: $line");
|
||||
return null;
|
||||
}
|
||||
|
||||
$command = preg_replace("#\\x1b\\x5b([^\\x1b]*\\x7e|[\\x40-\\x50])#", "", trim($command)) ?? throw new AssumptionFailedError("This regex is assumed to be valid");
|
||||
$command = preg_replace('/[[:cntrl:]]/', '', $command) ?? throw new AssumptionFailedError("This regex is assumed to be valid");
|
||||
|
71
src/console/ConsoleReaderChildProcessUtils.php
Normal file
71
src/console/ConsoleReaderChildProcessUtils.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?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\console;
|
||||
|
||||
use function hash;
|
||||
use function strlen;
|
||||
use function strrpos;
|
||||
use function substr;
|
||||
|
||||
final class ConsoleReaderChildProcessUtils{
|
||||
public const TOKEN_DELIMITER = ":";
|
||||
public const TOKEN_HASH_ALGO = "xxh3";
|
||||
|
||||
private function __construct(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an IPC message to transmit a user's input command to the parent process.
|
||||
*
|
||||
* Unfortunately we can't currently provide IPC pipes other than stdout/stderr to subprocesses on Windows, so this
|
||||
* adds a hash of the user input (with a counter as salt) to prevent unintended process output (like error messages)
|
||||
* from being treated as user input.
|
||||
*/
|
||||
public static function createMessage(string $line, int &$counter) : string{
|
||||
$token = hash(self::TOKEN_HASH_ALGO, $line, options: ['seed' => $counter]);
|
||||
$counter++;
|
||||
return $line . self::TOKEN_DELIMITER . $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a command from an IPC message from the console reader subprocess.
|
||||
* Returns the user's input command, or null if this isn't a user input.
|
||||
*/
|
||||
public static function parseMessage(string $message, int &$counter) : ?string{
|
||||
$delimiterPos = strrpos($message, self::TOKEN_DELIMITER);
|
||||
if($delimiterPos !== false){
|
||||
$left = substr($message, 0, $delimiterPos);
|
||||
$right = substr($message, $delimiterPos + strlen(self::TOKEN_DELIMITER));
|
||||
$expectedToken = hash(self::TOKEN_HASH_ALGO, $left, options: ['seed' => $counter]);
|
||||
|
||||
if($expectedToken === $right){
|
||||
$counter++;
|
||||
return $left;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -110,14 +110,15 @@ class CraftingManager{
|
||||
|
||||
/**
|
||||
* @param Item[] $items
|
||||
* @phpstan-param list<Item> $items
|
||||
*
|
||||
* @return Item[]
|
||||
* @phpstan-return list<Item>
|
||||
*/
|
||||
private static function pack(array $items) : array{
|
||||
/** @var Item[] $result */
|
||||
$result = [];
|
||||
|
||||
foreach($items as $i => $item){
|
||||
foreach($items as $item){
|
||||
foreach($result as $otherItem){
|
||||
if($item->canStackWith($otherItem)){
|
||||
$otherItem->setCount($otherItem->getCount() + $item->getCount());
|
||||
@ -134,6 +135,7 @@ class CraftingManager{
|
||||
|
||||
/**
|
||||
* @param Item[] $outputs
|
||||
* @phpstan-param list<Item> $outputs
|
||||
*/
|
||||
private static function hashOutputs(array $outputs) : string{
|
||||
$outputs = self::pack($outputs);
|
||||
|
@ -193,7 +193,7 @@ final class CraftingManagerFromDataHelper{
|
||||
*/
|
||||
private static function loadJsonObjectListIntoModel(\JsonMapper $mapper, string $modelClass, array $data) : array{
|
||||
$result = [];
|
||||
foreach($data as $i => $item){
|
||||
foreach(Utils::promoteKeys($data) as $i => $item){
|
||||
if(!is_object($item)){
|
||||
throw new SavedDataLoadingException("Invalid entry at index $i: expected object, got " . get_debug_type($item));
|
||||
}
|
||||
@ -275,7 +275,8 @@ final class CraftingManagerFromDataHelper{
|
||||
"furnace" => FurnaceType::FURNACE,
|
||||
"blast_furnace" => FurnaceType::BLAST_FURNACE,
|
||||
"smoker" => FurnaceType::SMOKER,
|
||||
//TODO: campfire
|
||||
"campfire" => FurnaceType::CAMPFIRE,
|
||||
"soul_campfire" => FurnaceType::SOUL_CAMPFIRE,
|
||||
default => null
|
||||
};
|
||||
if($furnaceType === null){
|
||||
|
@ -30,6 +30,7 @@ interface CraftingRecipe{
|
||||
* Returns a list of items needed to craft this recipe. This MUST NOT include Air items or items with a zero count.
|
||||
*
|
||||
* @return RecipeIngredient[]
|
||||
* @phpstan-return list<RecipeIngredient>
|
||||
*/
|
||||
public function getIngredientList() : array;
|
||||
|
||||
@ -37,6 +38,7 @@ interface CraftingRecipe{
|
||||
* Returns a list of results this recipe will produce when the inputs in the given crafting grid are consumed.
|
||||
*
|
||||
* @return Item[]
|
||||
* @phpstan-return list<Item>
|
||||
*/
|
||||
public function getResultsFor(CraftingGrid $grid) : array;
|
||||
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\crafting;
|
||||
|
||||
use pocketmine\utils\LegacyEnumShimTrait;
|
||||
use pocketmine\world\sound\BlastFurnaceSound;
|
||||
use pocketmine\world\sound\CampfireSound;
|
||||
use pocketmine\world\sound\FurnaceSound;
|
||||
use pocketmine\world\sound\SmokerSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
@ -35,8 +36,10 @@ use function spl_object_id;
|
||||
* These are retained for backwards compatibility only.
|
||||
*
|
||||
* @method static FurnaceType BLAST_FURNACE()
|
||||
* @method static FurnaceType CAMPFIRE()
|
||||
* @method static FurnaceType FURNACE()
|
||||
* @method static FurnaceType SMOKER()
|
||||
* @method static FurnaceType SOUL_CAMPFIRE()
|
||||
*
|
||||
* @phpstan-type TMetadata array{0: int, 1: Sound}
|
||||
*/
|
||||
@ -46,6 +49,8 @@ enum FurnaceType{
|
||||
case FURNACE;
|
||||
case BLAST_FURNACE;
|
||||
case SMOKER;
|
||||
case CAMPFIRE;
|
||||
case SOUL_CAMPFIRE;
|
||||
|
||||
/**
|
||||
* @phpstan-return TMetadata
|
||||
@ -58,6 +63,7 @@ enum FurnaceType{
|
||||
self::FURNACE => [200, new FurnaceSound()],
|
||||
self::BLAST_FURNACE => [100, new BlastFurnaceSound()],
|
||||
self::SMOKER => [100, new SmokerSound()],
|
||||
self::CAMPFIRE, self::SOUL_CAMPFIRE => [600, new CampfireSound()]
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -32,11 +32,20 @@ use function str_contains;
|
||||
use function strlen;
|
||||
|
||||
class ShapedRecipe implements CraftingRecipe{
|
||||
/** @var string[] */
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
private array $shape = [];
|
||||
/** @var RecipeIngredient[] char => RecipeIngredient map */
|
||||
/**
|
||||
* @var RecipeIngredient[] char => RecipeIngredient map
|
||||
* @phpstan-var array<string, RecipeIngredient>
|
||||
*/
|
||||
private array $ingredientList = [];
|
||||
/** @var Item[] */
|
||||
/**
|
||||
* @var Item[]
|
||||
* @phpstan-var list<Item>
|
||||
*/
|
||||
private array $results = [];
|
||||
|
||||
private int $height;
|
||||
@ -56,6 +65,10 @@ class ShapedRecipe implements CraftingRecipe{
|
||||
* @param Item[] $results List of items that this recipe produces when crafted.
|
||||
*
|
||||
* Note: Recipes **do not** need to be square. Do NOT add padding for empty rows/columns.
|
||||
*
|
||||
* @phpstan-param list<string> $shape
|
||||
* @phpstan-param array<string, RecipeIngredient> $ingredients
|
||||
* @phpstan-param list<Item> $results
|
||||
*/
|
||||
public function __construct(array $shape, array $ingredients, array $results){
|
||||
$this->height = count($shape);
|
||||
@ -84,7 +97,7 @@ class ShapedRecipe implements CraftingRecipe{
|
||||
|
||||
$this->shape = $shape;
|
||||
|
||||
foreach($ingredients as $char => $i){
|
||||
foreach(Utils::stringifyKeys($ingredients) as $char => $i){
|
||||
if(!str_contains(implode($this->shape), $char)){
|
||||
throw new \InvalidArgumentException("Symbol '$char' does not appear in the recipe shape");
|
||||
}
|
||||
@ -105,6 +118,7 @@ class ShapedRecipe implements CraftingRecipe{
|
||||
|
||||
/**
|
||||
* @return Item[]
|
||||
* @phpstan-return list<Item>
|
||||
*/
|
||||
public function getResults() : array{
|
||||
return Utils::cloneObjectArray($this->results);
|
||||
@ -112,6 +126,7 @@ class ShapedRecipe implements CraftingRecipe{
|
||||
|
||||
/**
|
||||
* @return Item[]
|
||||
* @phpstan-return list<Item>
|
||||
*/
|
||||
public function getResultsFor(CraftingGrid $grid) : array{
|
||||
return $this->getResults();
|
||||
@ -119,6 +134,7 @@ class ShapedRecipe implements CraftingRecipe{
|
||||
|
||||
/**
|
||||
* @return (RecipeIngredient|null)[][]
|
||||
* @phpstan-return list<list<RecipeIngredient|null>>
|
||||
*/
|
||||
public function getIngredientMap() : array{
|
||||
$ingredients = [];
|
||||
@ -132,9 +148,6 @@ class ShapedRecipe implements CraftingRecipe{
|
||||
return $ingredients;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RecipeIngredient[]
|
||||
*/
|
||||
public function getIngredientList() : array{
|
||||
$ingredients = [];
|
||||
|
||||
@ -157,6 +170,7 @@ class ShapedRecipe implements CraftingRecipe{
|
||||
/**
|
||||
* Returns an array of strings containing characters representing the recipe's shape.
|
||||
* @return string[]
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
public function getShape() : array{
|
||||
return $this->shape;
|
||||
|
@ -28,15 +28,24 @@ use pocketmine\utils\Utils;
|
||||
use function count;
|
||||
|
||||
class ShapelessRecipe implements CraftingRecipe{
|
||||
/** @var RecipeIngredient[] */
|
||||
/**
|
||||
* @var RecipeIngredient[]
|
||||
* @phpstan-var list<RecipeIngredient>
|
||||
*/
|
||||
private array $ingredients = [];
|
||||
/** @var Item[] */
|
||||
/**
|
||||
* @var Item[]
|
||||
* @phpstan-var list<Item>
|
||||
*/
|
||||
private array $results;
|
||||
private ShapelessRecipeType $type;
|
||||
|
||||
/**
|
||||
* @param RecipeIngredient[] $ingredients No more than 9 total. This applies to sum of item stack counts, not count of array.
|
||||
* @param Item[] $results List of result items created by this recipe.
|
||||
*
|
||||
* @phpstan-param list<RecipeIngredient> $ingredients
|
||||
* @phpstan-param list<Item> $results
|
||||
*/
|
||||
public function __construct(array $ingredients, array $results, ShapelessRecipeType $type){
|
||||
$this->type = $type;
|
||||
@ -50,6 +59,7 @@ class ShapelessRecipe implements CraftingRecipe{
|
||||
|
||||
/**
|
||||
* @return Item[]
|
||||
* @phpstan-return list<Item>
|
||||
*/
|
||||
public function getResults() : array{
|
||||
return Utils::cloneObjectArray($this->results);
|
||||
@ -63,9 +73,6 @@ class ShapelessRecipe implements CraftingRecipe{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RecipeIngredient[]
|
||||
*/
|
||||
public function getIngredientList() : array{
|
||||
return $this->ingredients;
|
||||
}
|
||||
|
@ -43,7 +43,10 @@ final class CrashDumpData implements \JsonSerializable{
|
||||
|
||||
public string $plugin = "";
|
||||
|
||||
/** @var string[] */
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var array<int, string>
|
||||
*/
|
||||
public array $code = [];
|
||||
|
||||
/** @var string[] */
|
||||
@ -55,7 +58,10 @@ final class CrashDumpData implements \JsonSerializable{
|
||||
*/
|
||||
public array $plugins = [];
|
||||
|
||||
/** @var string[] */
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
public array $parameters = [];
|
||||
|
||||
public string $serverDotProperties = "";
|
||||
|
@ -56,9 +56,11 @@ final class BannerPatternTypeIdMap{
|
||||
BannerPatternType::DIAGONAL_UP_LEFT => "ld",
|
||||
BannerPatternType::DIAGONAL_UP_RIGHT => "rud",
|
||||
BannerPatternType::FLOWER => "flo",
|
||||
BannerPatternType::FLOW => "flw",
|
||||
BannerPatternType::GLOBE => "glb",
|
||||
BannerPatternType::GRADIENT => "gra",
|
||||
BannerPatternType::GRADIENT_UP => "gru",
|
||||
BannerPatternType::GUSTER => "gus",
|
||||
BannerPatternType::HALF_HORIZONTAL => "hh",
|
||||
BannerPatternType::HALF_HORIZONTAL_BOTTOM => "hhb",
|
||||
BannerPatternType::HALF_VERTICAL => "vh",
|
||||
|
@ -35,6 +35,7 @@ final class BedrockDataFiles{
|
||||
public const BIOME_DEFINITIONS_FULL_NBT = BEDROCK_DATA_PATH . '/biome_definitions_full.nbt';
|
||||
public const BIOME_ID_MAP_JSON = BEDROCK_DATA_PATH . '/biome_id_map.json';
|
||||
public const BLOCK_ID_TO_ITEM_ID_MAP_JSON = BEDROCK_DATA_PATH . '/block_id_to_item_id_map.json';
|
||||
public const BLOCK_PROPERTIES_TABLE_JSON = BEDROCK_DATA_PATH . '/block_properties_table.json';
|
||||
public const BLOCK_STATE_META_MAP_JSON = BEDROCK_DATA_PATH . '/block_state_meta_map.json';
|
||||
public const CANONICAL_BLOCK_STATES_NBT = BEDROCK_DATA_PATH . '/canonical_block_states.nbt';
|
||||
public const COMMAND_ARG_TYPES_JSON = BEDROCK_DATA_PATH . '/command_arg_types.json';
|
||||
|
@ -43,6 +43,7 @@ final class EnchantmentIdMap{
|
||||
$this->register(EnchantmentIds::PROJECTILE_PROTECTION, VanillaEnchantments::PROJECTILE_PROTECTION());
|
||||
$this->register(EnchantmentIds::THORNS, VanillaEnchantments::THORNS());
|
||||
$this->register(EnchantmentIds::RESPIRATION, VanillaEnchantments::RESPIRATION());
|
||||
$this->register(EnchantmentIds::AQUA_AFFINITY, VanillaEnchantments::AQUA_AFFINITY());
|
||||
|
||||
$this->register(EnchantmentIds::SHARPNESS, VanillaEnchantments::SHARPNESS());
|
||||
//TODO: smite, bane of arthropods (these don't make sense now because their applicable mobs don't exist yet)
|
||||
@ -65,5 +66,7 @@ final class EnchantmentIdMap{
|
||||
$this->register(EnchantmentIds::VANISHING, VanillaEnchantments::VANISHING());
|
||||
|
||||
$this->register(EnchantmentIds::SWIFT_SNEAK, VanillaEnchantments::SWIFT_SNEAK());
|
||||
|
||||
$this->register(EnchantmentIds::FROST_WALKER, VanillaEnchantments::FROST_WALKER());
|
||||
}
|
||||
}
|
||||
|
48
src/data/bedrock/GoatHornTypeIdMap.php
Normal file
48
src/data/bedrock/GoatHornTypeIdMap.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\bedrock;
|
||||
|
||||
use pocketmine\item\GoatHornType;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
|
||||
final class GoatHornTypeIdMap{
|
||||
use SingletonTrait;
|
||||
/** @phpstan-use IntSaveIdMapTrait<GoatHornType> */
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
foreach(GoatHornType::cases() as $case){
|
||||
$this->register(match($case){
|
||||
GoatHornType::PONDER => GoatHornTypeIds::PONDER,
|
||||
GoatHornType::SING => GoatHornTypeIds::SING,
|
||||
GoatHornType::SEEK => GoatHornTypeIds::SEEK,
|
||||
GoatHornType::FEEL => GoatHornTypeIds::FEEL,
|
||||
GoatHornType::ADMIRE => GoatHornTypeIds::ADMIRE,
|
||||
GoatHornType::CALL => GoatHornTypeIds::CALL,
|
||||
GoatHornType::YEARN => GoatHornTypeIds::YEARN,
|
||||
GoatHornType::DREAM => GoatHornTypeIds::DREAM
|
||||
}, $case);
|
||||
}
|
||||
}
|
||||
}
|
35
src/data/bedrock/GoatHornTypeIds.php
Normal file
35
src/data/bedrock/GoatHornTypeIds.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\bedrock;
|
||||
|
||||
final class GoatHornTypeIds{
|
||||
public const PONDER = 0;
|
||||
public const SING = 1;
|
||||
public const SEEK = 2;
|
||||
public const FEEL = 3;
|
||||
public const ADMIRE = 4;
|
||||
public const CALL = 5;
|
||||
public const YEARN = 6;
|
||||
public const DREAM = 7;
|
||||
}
|
@ -48,7 +48,7 @@ final class ItemTagToIdMap{
|
||||
throw new AssumptionFailedError("Invalid item tag map, expected array");
|
||||
}
|
||||
$cleanMap = [];
|
||||
foreach($map as $tagName => $ids){
|
||||
foreach(Utils::promoteKeys($map) as $tagName => $ids){
|
||||
if(!is_string($tagName)){
|
||||
throw new AssumptionFailedError("Invalid item tag name $tagName, expected string as key");
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\data\bedrock;
|
||||
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Filesystem;
|
||||
use pocketmine\utils\Utils;
|
||||
use function is_array;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
@ -43,7 +44,7 @@ abstract class LegacyToStringIdMap{
|
||||
if(!is_array($stringToLegacyId)){
|
||||
throw new AssumptionFailedError("Invalid format of ID map");
|
||||
}
|
||||
foreach($stringToLegacyId as $stringId => $legacyId){
|
||||
foreach(Utils::promoteKeys($stringToLegacyId) as $stringId => $legacyId){
|
||||
if(!is_string($stringId) || !is_int($legacyId)){
|
||||
throw new AssumptionFailedError("ID map should have string keys and int values");
|
||||
}
|
||||
|
@ -45,8 +45,8 @@ final class BlockStateData{
|
||||
public const CURRENT_VERSION =
|
||||
(1 << 24) | //major
|
||||
(21 << 16) | //minor
|
||||
(0 << 8) | //patch
|
||||
(3); //revision
|
||||
(40 << 8) | //patch
|
||||
(1); //revision
|
||||
|
||||
public const TAG_NAME = "name";
|
||||
public const TAG_STATES = "states";
|
||||
|
@ -34,7 +34,6 @@ final class BlockStateNames{
|
||||
public const ACTIVE = "active";
|
||||
public const AGE = "age";
|
||||
public const AGE_BIT = "age_bit";
|
||||
public const ALLOW_UNDERWATER_BIT = "allow_underwater_bit";
|
||||
public const ATTACHED_BIT = "attached_bit";
|
||||
public const ATTACHMENT = "attachment";
|
||||
public const BAMBOO_LEAF_SIZE = "bamboo_leaf_size";
|
||||
@ -42,7 +41,6 @@ final class BlockStateNames{
|
||||
public const BIG_DRIPLEAF_HEAD = "big_dripleaf_head";
|
||||
public const BIG_DRIPLEAF_TILT = "big_dripleaf_tilt";
|
||||
public const BITE_COUNTER = "bite_counter";
|
||||
public const BLOCK_LIGHT_LEVEL = "block_light_level";
|
||||
public const BLOOM = "bloom";
|
||||
public const BOOKS_STORED = "books_stored";
|
||||
public const BREWING_STAND_SLOT_A_BIT = "brewing_stand_slot_a_bit";
|
||||
@ -53,23 +51,17 @@ final class BlockStateNames{
|
||||
public const CAN_SUMMON = "can_summon";
|
||||
public const CANDLES = "candles";
|
||||
public const CAULDRON_LIQUID = "cauldron_liquid";
|
||||
public const CHEMISTRY_TABLE_TYPE = "chemistry_table_type";
|
||||
public const CHISEL_TYPE = "chisel_type";
|
||||
public const CLUSTER_COUNT = "cluster_count";
|
||||
public const COLOR_BIT = "color_bit";
|
||||
public const COMPOSTER_FILL_LEVEL = "composter_fill_level";
|
||||
public const CONDITIONAL_BIT = "conditional_bit";
|
||||
public const CORAL_DIRECTION = "coral_direction";
|
||||
public const CORAL_FAN_DIRECTION = "coral_fan_direction";
|
||||
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";
|
||||
public const DIRECTION = "direction";
|
||||
public const DIRT_TYPE = "dirt_type";
|
||||
public const DISARMED_BIT = "disarmed_bit";
|
||||
public const DOOR_HINGE_BIT = "door_hinge_bit";
|
||||
public const DRAG_DOWN = "drag_down";
|
||||
@ -100,7 +92,6 @@ final class BlockStateNames{
|
||||
public const MC_FACING_DIRECTION = "minecraft:facing_direction";
|
||||
public const MC_VERTICAL_HALF = "minecraft:vertical_half";
|
||||
public const MOISTURIZED_AMOUNT = "moisturized_amount";
|
||||
public const MONSTER_EGG_STONE_TYPE = "monster_egg_stone_type";
|
||||
public const MULTI_FACE_DIRECTION_BITS = "multi_face_direction_bits";
|
||||
public const OCCUPIED_BIT = "occupied_bit";
|
||||
public const OMINOUS = "ominous";
|
||||
@ -112,7 +103,6 @@ final class BlockStateNames{
|
||||
public const PILLAR_AXIS = "pillar_axis";
|
||||
public const PORTAL_AXIS = "portal_axis";
|
||||
public const POWERED_BIT = "powered_bit";
|
||||
public const PRISMARINE_BLOCK_TYPE = "prismarine_block_type";
|
||||
public const PROPAGULE_STAGE = "propagule_stage";
|
||||
public const RAIL_DATA_BIT = "rail_data_bit";
|
||||
public const RAIL_DIRECTION = "rail_direction";
|
||||
@ -120,21 +110,11 @@ final class BlockStateNames{
|
||||
public const REPEATER_DELAY = "repeater_delay";
|
||||
public const RESPAWN_ANCHOR_CHARGE = "respawn_anchor_charge";
|
||||
public const ROTATION = "rotation";
|
||||
public const SAND_STONE_TYPE = "sand_stone_type";
|
||||
public const SAND_TYPE = "sand_type";
|
||||
public const SCULK_SENSOR_PHASE = "sculk_sensor_phase";
|
||||
public const SEA_GRASS_TYPE = "sea_grass_type";
|
||||
public const SPONGE_TYPE = "sponge_type";
|
||||
public const STABILITY = "stability";
|
||||
public const STABILITY_CHECK = "stability_check";
|
||||
public const STONE_BRICK_TYPE = "stone_brick_type";
|
||||
public const STONE_SLAB_TYPE = "stone_slab_type";
|
||||
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 STRIPPED_BIT = "stripped_bit";
|
||||
public const STRUCTURE_BLOCK_TYPE = "structure_block_type";
|
||||
public const STRUCTURE_VOID_TYPE = "structure_void_type";
|
||||
public const SUSPENDED_BIT = "suspended_bit";
|
||||
public const TOGGLE_BIT = "toggle_bit";
|
||||
public const TORCH_FACING_DIRECTION = "torch_facing_direction";
|
||||
@ -147,7 +127,6 @@ final class BlockStateNames{
|
||||
public const UPSIDE_DOWN_BIT = "upside_down_bit";
|
||||
public const VAULT_STATE = "vault_state";
|
||||
public const VINE_DIRECTION_BITS = "vine_direction_bits";
|
||||
public const WALL_BLOCK_TYPE = "wall_block_type";
|
||||
public const WALL_CONNECTION_TYPE_EAST = "wall_connection_type_east";
|
||||
public const WALL_CONNECTION_TYPE_NORTH = "wall_connection_type_north";
|
||||
public const WALL_CONNECTION_TYPE_SOUTH = "wall_connection_type_south";
|
||||
|
@ -52,28 +52,10 @@ final class BlockStateStringValues{
|
||||
public const CAULDRON_LIQUID_POWDER_SNOW = "powder_snow";
|
||||
public const CAULDRON_LIQUID_WATER = "water";
|
||||
|
||||
public const CHEMISTRY_TABLE_TYPE_COMPOUND_CREATOR = "compound_creator";
|
||||
public const CHEMISTRY_TABLE_TYPE_ELEMENT_CONSTRUCTOR = "element_constructor";
|
||||
public const CHEMISTRY_TABLE_TYPE_LAB_TABLE = "lab_table";
|
||||
public const CHEMISTRY_TABLE_TYPE_MATERIAL_REDUCER = "material_reducer";
|
||||
|
||||
public const CHISEL_TYPE_CHISELED = "chiseled";
|
||||
public const CHISEL_TYPE_DEFAULT = "default";
|
||||
public const CHISEL_TYPE_LINES = "lines";
|
||||
public const CHISEL_TYPE_SMOOTH = "smooth";
|
||||
|
||||
public const CRACKED_STATE_CRACKED = "cracked";
|
||||
public const CRACKED_STATE_MAX_CRACKED = "max_cracked";
|
||||
public const CRACKED_STATE_NO_CRACKS = "no_cracks";
|
||||
|
||||
public const DAMAGE_BROKEN = "broken";
|
||||
public const DAMAGE_SLIGHTLY_DAMAGED = "slightly_damaged";
|
||||
public const DAMAGE_UNDAMAGED = "undamaged";
|
||||
public const DAMAGE_VERY_DAMAGED = "very_damaged";
|
||||
|
||||
public const DIRT_TYPE_COARSE = "coarse";
|
||||
public const DIRT_TYPE_NORMAL = "normal";
|
||||
|
||||
public const DRIPSTONE_THICKNESS_BASE = "base";
|
||||
public const DRIPSTONE_THICKNESS_FRUSTUM = "frustum";
|
||||
public const DRIPSTONE_THICKNESS_MERGE = "merge";
|
||||
@ -111,13 +93,6 @@ final class BlockStateStringValues{
|
||||
public const MC_VERTICAL_HALF_BOTTOM = "bottom";
|
||||
public const MC_VERTICAL_HALF_TOP = "top";
|
||||
|
||||
public const MONSTER_EGG_STONE_TYPE_CHISELED_STONE_BRICK = "chiseled_stone_brick";
|
||||
public const MONSTER_EGG_STONE_TYPE_COBBLESTONE = "cobblestone";
|
||||
public const MONSTER_EGG_STONE_TYPE_CRACKED_STONE_BRICK = "cracked_stone_brick";
|
||||
public const MONSTER_EGG_STONE_TYPE_MOSSY_STONE_BRICK = "mossy_stone_brick";
|
||||
public const MONSTER_EGG_STONE_TYPE_STONE = "stone";
|
||||
public const MONSTER_EGG_STONE_TYPE_STONE_BRICK = "stone_brick";
|
||||
|
||||
public const ORIENTATION_DOWN_EAST = "down_east";
|
||||
public const ORIENTATION_DOWN_NORTH = "down_north";
|
||||
public const ORIENTATION_DOWN_SOUTH = "down_south";
|
||||
@ -139,64 +114,10 @@ final class BlockStateStringValues{
|
||||
public const PORTAL_AXIS_X = "x";
|
||||
public const PORTAL_AXIS_Z = "z";
|
||||
|
||||
public const PRISMARINE_BLOCK_TYPE_BRICKS = "bricks";
|
||||
public const PRISMARINE_BLOCK_TYPE_DARK = "dark";
|
||||
public const PRISMARINE_BLOCK_TYPE_DEFAULT = "default";
|
||||
|
||||
public const SAND_STONE_TYPE_CUT = "cut";
|
||||
public const SAND_STONE_TYPE_DEFAULT = "default";
|
||||
public const SAND_STONE_TYPE_HEIROGLYPHS = "heiroglyphs";
|
||||
public const SAND_STONE_TYPE_SMOOTH = "smooth";
|
||||
|
||||
public const SAND_TYPE_NORMAL = "normal";
|
||||
public const SAND_TYPE_RED = "red";
|
||||
|
||||
public const SEA_GRASS_TYPE_DEFAULT = "default";
|
||||
public const SEA_GRASS_TYPE_DOUBLE_BOT = "double_bot";
|
||||
public const SEA_GRASS_TYPE_DOUBLE_TOP = "double_top";
|
||||
|
||||
public const SPONGE_TYPE_DRY = "dry";
|
||||
public const SPONGE_TYPE_WET = "wet";
|
||||
|
||||
public const STONE_BRICK_TYPE_CHISELED = "chiseled";
|
||||
public const STONE_BRICK_TYPE_CRACKED = "cracked";
|
||||
public const STONE_BRICK_TYPE_DEFAULT = "default";
|
||||
public const STONE_BRICK_TYPE_MOSSY = "mossy";
|
||||
public const STONE_BRICK_TYPE_SMOOTH = "smooth";
|
||||
|
||||
public const STONE_SLAB_TYPE_BRICK = "brick";
|
||||
public const STONE_SLAB_TYPE_COBBLESTONE = "cobblestone";
|
||||
public const STONE_SLAB_TYPE_NETHER_BRICK = "nether_brick";
|
||||
public const STONE_SLAB_TYPE_QUARTZ = "quartz";
|
||||
public const STONE_SLAB_TYPE_SANDSTONE = "sandstone";
|
||||
public const STONE_SLAB_TYPE_SMOOTH_STONE = "smooth_stone";
|
||||
public const STONE_SLAB_TYPE_STONE_BRICK = "stone_brick";
|
||||
public const STONE_SLAB_TYPE_WOOD = "wood";
|
||||
|
||||
public const STONE_SLAB_TYPE_2_MOSSY_COBBLESTONE = "mossy_cobblestone";
|
||||
public const STONE_SLAB_TYPE_2_PRISMARINE_BRICK = "prismarine_brick";
|
||||
public const STONE_SLAB_TYPE_2_PRISMARINE_DARK = "prismarine_dark";
|
||||
public const STONE_SLAB_TYPE_2_PRISMARINE_ROUGH = "prismarine_rough";
|
||||
public const STONE_SLAB_TYPE_2_PURPUR = "purpur";
|
||||
public const STONE_SLAB_TYPE_2_RED_NETHER_BRICK = "red_nether_brick";
|
||||
public const STONE_SLAB_TYPE_2_RED_SANDSTONE = "red_sandstone";
|
||||
public const STONE_SLAB_TYPE_2_SMOOTH_SANDSTONE = "smooth_sandstone";
|
||||
|
||||
public const STONE_SLAB_TYPE_3_ANDESITE = "andesite";
|
||||
public const STONE_SLAB_TYPE_3_DIORITE = "diorite";
|
||||
public const STONE_SLAB_TYPE_3_END_STONE_BRICK = "end_stone_brick";
|
||||
public const STONE_SLAB_TYPE_3_GRANITE = "granite";
|
||||
public const STONE_SLAB_TYPE_3_POLISHED_ANDESITE = "polished_andesite";
|
||||
public const STONE_SLAB_TYPE_3_POLISHED_DIORITE = "polished_diorite";
|
||||
public const STONE_SLAB_TYPE_3_POLISHED_GRANITE = "polished_granite";
|
||||
public const STONE_SLAB_TYPE_3_SMOOTH_RED_SANDSTONE = "smooth_red_sandstone";
|
||||
|
||||
public const STONE_SLAB_TYPE_4_CUT_RED_SANDSTONE = "cut_red_sandstone";
|
||||
public const STONE_SLAB_TYPE_4_CUT_SANDSTONE = "cut_sandstone";
|
||||
public const STONE_SLAB_TYPE_4_MOSSY_STONE_BRICK = "mossy_stone_brick";
|
||||
public const STONE_SLAB_TYPE_4_SMOOTH_QUARTZ = "smooth_quartz";
|
||||
public const STONE_SLAB_TYPE_4_STONE = "stone";
|
||||
|
||||
public const STRUCTURE_BLOCK_TYPE_CORNER = "corner";
|
||||
public const STRUCTURE_BLOCK_TYPE_DATA = "data";
|
||||
public const STRUCTURE_BLOCK_TYPE_EXPORT = "export";
|
||||
@ -204,9 +125,6 @@ final class BlockStateStringValues{
|
||||
public const STRUCTURE_BLOCK_TYPE_LOAD = "load";
|
||||
public const STRUCTURE_BLOCK_TYPE_SAVE = "save";
|
||||
|
||||
public const STRUCTURE_VOID_TYPE_AIR = "air";
|
||||
public const STRUCTURE_VOID_TYPE_VOID = "void";
|
||||
|
||||
public const TORCH_FACING_DIRECTION_EAST = "east";
|
||||
public const TORCH_FACING_DIRECTION_NORTH = "north";
|
||||
public const TORCH_FACING_DIRECTION_SOUTH = "south";
|
||||
@ -224,21 +142,6 @@ final class BlockStateStringValues{
|
||||
public const VAULT_STATE_INACTIVE = "inactive";
|
||||
public const VAULT_STATE_UNLOCKING = "unlocking";
|
||||
|
||||
public const WALL_BLOCK_TYPE_ANDESITE = "andesite";
|
||||
public const WALL_BLOCK_TYPE_BRICK = "brick";
|
||||
public const WALL_BLOCK_TYPE_COBBLESTONE = "cobblestone";
|
||||
public const WALL_BLOCK_TYPE_DIORITE = "diorite";
|
||||
public const WALL_BLOCK_TYPE_END_BRICK = "end_brick";
|
||||
public const WALL_BLOCK_TYPE_GRANITE = "granite";
|
||||
public const WALL_BLOCK_TYPE_MOSSY_COBBLESTONE = "mossy_cobblestone";
|
||||
public const WALL_BLOCK_TYPE_MOSSY_STONE_BRICK = "mossy_stone_brick";
|
||||
public const WALL_BLOCK_TYPE_NETHER_BRICK = "nether_brick";
|
||||
public const WALL_BLOCK_TYPE_PRISMARINE = "prismarine";
|
||||
public const WALL_BLOCK_TYPE_RED_NETHER_BRICK = "red_nether_brick";
|
||||
public const WALL_BLOCK_TYPE_RED_SANDSTONE = "red_sandstone";
|
||||
public const WALL_BLOCK_TYPE_SANDSTONE = "sandstone";
|
||||
public const WALL_BLOCK_TYPE_STONE_BRICK = "stone_brick";
|
||||
|
||||
public const WALL_CONNECTION_TYPE_EAST_NONE = "none";
|
||||
public const WALL_CONNECTION_TYPE_EAST_SHORT = "short";
|
||||
public const WALL_CONNECTION_TYPE_EAST_TALL = "tall";
|
||||
|
@ -56,7 +56,10 @@ final class BlockTypeNames{
|
||||
public const AMETHYST_CLUSTER = "minecraft:amethyst_cluster";
|
||||
public const ANCIENT_DEBRIS = "minecraft:ancient_debris";
|
||||
public const ANDESITE = "minecraft:andesite";
|
||||
public const ANDESITE_DOUBLE_SLAB = "minecraft:andesite_double_slab";
|
||||
public const ANDESITE_SLAB = "minecraft:andesite_slab";
|
||||
public const ANDESITE_STAIRS = "minecraft:andesite_stairs";
|
||||
public const ANDESITE_WALL = "minecraft:andesite_wall";
|
||||
public const ANVIL = "minecraft:anvil";
|
||||
public const AZALEA = "minecraft:azalea";
|
||||
public const AZALEA_LEAVES = "minecraft:azalea_leaves";
|
||||
@ -146,10 +149,13 @@ final class BlockTypeNames{
|
||||
public const BRAIN_CORAL = "minecraft:brain_coral";
|
||||
public const BRAIN_CORAL_BLOCK = "minecraft:brain_coral_block";
|
||||
public const BRAIN_CORAL_FAN = "minecraft:brain_coral_fan";
|
||||
public const BRAIN_CORAL_WALL_FAN = "minecraft:brain_coral_wall_fan";
|
||||
public const BREWING_STAND = "minecraft:brewing_stand";
|
||||
public const BRICK_BLOCK = "minecraft:brick_block";
|
||||
public const BRICK_DOUBLE_SLAB = "minecraft:brick_double_slab";
|
||||
public const BRICK_SLAB = "minecraft:brick_slab";
|
||||
public const BRICK_STAIRS = "minecraft:brick_stairs";
|
||||
public const BRICK_WALL = "minecraft:brick_wall";
|
||||
public const BROWN_CANDLE = "minecraft:brown_candle";
|
||||
public const BROWN_CANDLE_CAKE = "minecraft:brown_candle_cake";
|
||||
public const BROWN_CARPET = "minecraft:brown_carpet";
|
||||
@ -167,6 +173,7 @@ final class BlockTypeNames{
|
||||
public const BUBBLE_CORAL = "minecraft:bubble_coral";
|
||||
public const BUBBLE_CORAL_BLOCK = "minecraft:bubble_coral_block";
|
||||
public const BUBBLE_CORAL_FAN = "minecraft:bubble_coral_fan";
|
||||
public const BUBBLE_CORAL_WALL_FAN = "minecraft:bubble_coral_wall_fan";
|
||||
public const BUDDING_AMETHYST = "minecraft:budding_amethyst";
|
||||
public const CACTUS = "minecraft:cactus";
|
||||
public const CAKE = "minecraft:cake";
|
||||
@ -186,7 +193,6 @@ final class BlockTypeNames{
|
||||
public const CHAIN = "minecraft:chain";
|
||||
public const CHAIN_COMMAND_BLOCK = "minecraft:chain_command_block";
|
||||
public const CHEMICAL_HEAT = "minecraft:chemical_heat";
|
||||
public const CHEMISTRY_TABLE = "minecraft:chemistry_table";
|
||||
public const CHERRY_BUTTON = "minecraft:cherry_button";
|
||||
public const CHERRY_DOOR = "minecraft:cherry_door";
|
||||
public const CHERRY_DOUBLE_SLAB = "minecraft:cherry_double_slab";
|
||||
@ -205,11 +211,16 @@ final class BlockTypeNames{
|
||||
public const CHERRY_WALL_SIGN = "minecraft:cherry_wall_sign";
|
||||
public const CHERRY_WOOD = "minecraft:cherry_wood";
|
||||
public const CHEST = "minecraft:chest";
|
||||
public const CHIPPED_ANVIL = "minecraft:chipped_anvil";
|
||||
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_QUARTZ_BLOCK = "minecraft:chiseled_quartz_block";
|
||||
public const CHISELED_RED_SANDSTONE = "minecraft:chiseled_red_sandstone";
|
||||
public const CHISELED_SANDSTONE = "minecraft:chiseled_sandstone";
|
||||
public const CHISELED_STONE_BRICKS = "minecraft:chiseled_stone_bricks";
|
||||
public const CHISELED_TUFF = "minecraft:chiseled_tuff";
|
||||
public const CHISELED_TUFF_BRICKS = "minecraft:chiseled_tuff_bricks";
|
||||
public const CHORUS_FLOWER = "minecraft:chorus_flower";
|
||||
@ -218,19 +229,24 @@ final class BlockTypeNames{
|
||||
public const CLIENT_REQUEST_PLACEHOLDER_BLOCK = "minecraft:client_request_placeholder_block";
|
||||
public const COAL_BLOCK = "minecraft:coal_block";
|
||||
public const COAL_ORE = "minecraft:coal_ore";
|
||||
public const COARSE_DIRT = "minecraft:coarse_dirt";
|
||||
public const COBBLED_DEEPSLATE = "minecraft:cobbled_deepslate";
|
||||
public const COBBLED_DEEPSLATE_DOUBLE_SLAB = "minecraft:cobbled_deepslate_double_slab";
|
||||
public const COBBLED_DEEPSLATE_SLAB = "minecraft:cobbled_deepslate_slab";
|
||||
public const COBBLED_DEEPSLATE_STAIRS = "minecraft:cobbled_deepslate_stairs";
|
||||
public const COBBLED_DEEPSLATE_WALL = "minecraft:cobbled_deepslate_wall";
|
||||
public const COBBLESTONE = "minecraft:cobblestone";
|
||||
public const COBBLESTONE_DOUBLE_SLAB = "minecraft:cobblestone_double_slab";
|
||||
public const COBBLESTONE_SLAB = "minecraft:cobblestone_slab";
|
||||
public const COBBLESTONE_WALL = "minecraft:cobblestone_wall";
|
||||
public const COCOA = "minecraft:cocoa";
|
||||
public const COLORED_TORCH_BP = "minecraft:colored_torch_bp";
|
||||
public const COLORED_TORCH_RG = "minecraft:colored_torch_rg";
|
||||
public const COLORED_TORCH_BLUE = "minecraft:colored_torch_blue";
|
||||
public const COLORED_TORCH_GREEN = "minecraft:colored_torch_green";
|
||||
public const COLORED_TORCH_PURPLE = "minecraft:colored_torch_purple";
|
||||
public const COLORED_TORCH_RED = "minecraft:colored_torch_red";
|
||||
public const COMMAND_BLOCK = "minecraft:command_block";
|
||||
public const COMPOSTER = "minecraft:composter";
|
||||
public const COMPOUND_CREATOR = "minecraft:compound_creator";
|
||||
public const CONDUIT = "minecraft:conduit";
|
||||
public const COPPER_BLOCK = "minecraft:copper_block";
|
||||
public const COPPER_BULB = "minecraft:copper_bulb";
|
||||
@ -238,16 +254,15 @@ final class BlockTypeNames{
|
||||
public const COPPER_GRATE = "minecraft:copper_grate";
|
||||
public const COPPER_ORE = "minecraft:copper_ore";
|
||||
public const COPPER_TRAPDOOR = "minecraft:copper_trapdoor";
|
||||
public const CORAL_FAN_HANG = "minecraft:coral_fan_hang";
|
||||
public const CORAL_FAN_HANG2 = "minecraft:coral_fan_hang2";
|
||||
public const CORAL_FAN_HANG3 = "minecraft:coral_fan_hang3";
|
||||
public const CORNFLOWER = "minecraft:cornflower";
|
||||
public const CRACKED_DEEPSLATE_BRICKS = "minecraft:cracked_deepslate_bricks";
|
||||
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 CRACKED_STONE_BRICKS = "minecraft:cracked_stone_bricks";
|
||||
public const CRAFTER = "minecraft:crafter";
|
||||
public const CRAFTING_TABLE = "minecraft:crafting_table";
|
||||
public const CREEPER_HEAD = "minecraft:creeper_head";
|
||||
public const CRIMSON_BUTTON = "minecraft:crimson_button";
|
||||
public const CRIMSON_DOOR = "minecraft:crimson_door";
|
||||
public const CRIMSON_DOUBLE_SLAB = "minecraft:crimson_double_slab";
|
||||
@ -270,6 +285,12 @@ final class BlockTypeNames{
|
||||
public const CUT_COPPER = "minecraft:cut_copper";
|
||||
public const CUT_COPPER_SLAB = "minecraft:cut_copper_slab";
|
||||
public const CUT_COPPER_STAIRS = "minecraft:cut_copper_stairs";
|
||||
public const CUT_RED_SANDSTONE = "minecraft:cut_red_sandstone";
|
||||
public const CUT_RED_SANDSTONE_DOUBLE_SLAB = "minecraft:cut_red_sandstone_double_slab";
|
||||
public const CUT_RED_SANDSTONE_SLAB = "minecraft:cut_red_sandstone_slab";
|
||||
public const CUT_SANDSTONE = "minecraft:cut_sandstone";
|
||||
public const CUT_SANDSTONE_DOUBLE_SLAB = "minecraft:cut_sandstone_double_slab";
|
||||
public const CUT_SANDSTONE_SLAB = "minecraft:cut_sandstone_slab";
|
||||
public const CYAN_CANDLE = "minecraft:cyan_candle";
|
||||
public const CYAN_CANDLE_CAKE = "minecraft:cyan_candle_cake";
|
||||
public const CYAN_CARPET = "minecraft:cyan_carpet";
|
||||
@ -281,6 +302,8 @@ final class BlockTypeNames{
|
||||
public const CYAN_STAINED_GLASS_PANE = "minecraft:cyan_stained_glass_pane";
|
||||
public const CYAN_TERRACOTTA = "minecraft:cyan_terracotta";
|
||||
public const CYAN_WOOL = "minecraft:cyan_wool";
|
||||
public const DAMAGED_ANVIL = "minecraft:damaged_anvil";
|
||||
public const DANDELION = "minecraft:dandelion";
|
||||
public const DARK_OAK_BUTTON = "minecraft:dark_oak_button";
|
||||
public const DARK_OAK_DOOR = "minecraft:dark_oak_door";
|
||||
public const DARK_OAK_DOUBLE_SLAB = "minecraft:dark_oak_double_slab";
|
||||
@ -296,6 +319,9 @@ final class BlockTypeNames{
|
||||
public const DARK_OAK_STAIRS = "minecraft:dark_oak_stairs";
|
||||
public const DARK_OAK_TRAPDOOR = "minecraft:dark_oak_trapdoor";
|
||||
public const DARK_OAK_WOOD = "minecraft:dark_oak_wood";
|
||||
public const DARK_PRISMARINE = "minecraft:dark_prismarine";
|
||||
public const DARK_PRISMARINE_DOUBLE_SLAB = "minecraft:dark_prismarine_double_slab";
|
||||
public const DARK_PRISMARINE_SLAB = "minecraft:dark_prismarine_slab";
|
||||
public const DARK_PRISMARINE_STAIRS = "minecraft:dark_prismarine_stairs";
|
||||
public const DARKOAK_STANDING_SIGN = "minecraft:darkoak_standing_sign";
|
||||
public const DARKOAK_WALL_SIGN = "minecraft:darkoak_wall_sign";
|
||||
@ -304,18 +330,23 @@ final class BlockTypeNames{
|
||||
public const DEAD_BRAIN_CORAL = "minecraft:dead_brain_coral";
|
||||
public const DEAD_BRAIN_CORAL_BLOCK = "minecraft:dead_brain_coral_block";
|
||||
public const DEAD_BRAIN_CORAL_FAN = "minecraft:dead_brain_coral_fan";
|
||||
public const DEAD_BRAIN_CORAL_WALL_FAN = "minecraft:dead_brain_coral_wall_fan";
|
||||
public const DEAD_BUBBLE_CORAL = "minecraft:dead_bubble_coral";
|
||||
public const DEAD_BUBBLE_CORAL_BLOCK = "minecraft:dead_bubble_coral_block";
|
||||
public const DEAD_BUBBLE_CORAL_FAN = "minecraft:dead_bubble_coral_fan";
|
||||
public const DEAD_BUBBLE_CORAL_WALL_FAN = "minecraft:dead_bubble_coral_wall_fan";
|
||||
public const DEAD_FIRE_CORAL = "minecraft:dead_fire_coral";
|
||||
public const DEAD_FIRE_CORAL_BLOCK = "minecraft:dead_fire_coral_block";
|
||||
public const DEAD_FIRE_CORAL_FAN = "minecraft:dead_fire_coral_fan";
|
||||
public const DEAD_FIRE_CORAL_WALL_FAN = "minecraft:dead_fire_coral_wall_fan";
|
||||
public const DEAD_HORN_CORAL = "minecraft:dead_horn_coral";
|
||||
public const DEAD_HORN_CORAL_BLOCK = "minecraft:dead_horn_coral_block";
|
||||
public const DEAD_HORN_CORAL_FAN = "minecraft:dead_horn_coral_fan";
|
||||
public const DEAD_HORN_CORAL_WALL_FAN = "minecraft:dead_horn_coral_wall_fan";
|
||||
public const DEAD_TUBE_CORAL = "minecraft:dead_tube_coral";
|
||||
public const DEAD_TUBE_CORAL_BLOCK = "minecraft:dead_tube_coral_block";
|
||||
public const DEAD_TUBE_CORAL_FAN = "minecraft:dead_tube_coral_fan";
|
||||
public const DEAD_TUBE_CORAL_WALL_FAN = "minecraft:dead_tube_coral_wall_fan";
|
||||
public const DEADBUSH = "minecraft:deadbush";
|
||||
public const DECORATED_POT = "minecraft:decorated_pot";
|
||||
public const DEEPSLATE = "minecraft:deepslate";
|
||||
@ -338,20 +369,23 @@ final class BlockTypeNames{
|
||||
public const DEEPSLATE_TILE_WALL = "minecraft:deepslate_tile_wall";
|
||||
public const DEEPSLATE_TILES = "minecraft:deepslate_tiles";
|
||||
public const DENY = "minecraft:deny";
|
||||
public const DEPRECATED_ANVIL = "minecraft:deprecated_anvil";
|
||||
public const DEPRECATED_PURPUR_BLOCK_1 = "minecraft:deprecated_purpur_block_1";
|
||||
public const DEPRECATED_PURPUR_BLOCK_2 = "minecraft:deprecated_purpur_block_2";
|
||||
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_DOUBLE_SLAB = "minecraft:diorite_double_slab";
|
||||
public const DIORITE_SLAB = "minecraft:diorite_slab";
|
||||
public const DIORITE_STAIRS = "minecraft:diorite_stairs";
|
||||
public const DIORITE_WALL = "minecraft:diorite_wall";
|
||||
public const DIRT = "minecraft:dirt";
|
||||
public const DIRT_WITH_ROOTS = "minecraft:dirt_with_roots";
|
||||
public const DISPENSER = "minecraft:dispenser";
|
||||
public const DOUBLE_CUT_COPPER_SLAB = "minecraft:double_cut_copper_slab";
|
||||
public const DOUBLE_STONE_BLOCK_SLAB = "minecraft:double_stone_block_slab";
|
||||
public const DOUBLE_STONE_BLOCK_SLAB2 = "minecraft:double_stone_block_slab2";
|
||||
public const DOUBLE_STONE_BLOCK_SLAB3 = "minecraft:double_stone_block_slab3";
|
||||
public const DOUBLE_STONE_BLOCK_SLAB4 = "minecraft:double_stone_block_slab4";
|
||||
public const DRAGON_EGG = "minecraft:dragon_egg";
|
||||
public const DRAGON_HEAD = "minecraft:dragon_head";
|
||||
public const DRIED_KELP_BLOCK = "minecraft:dried_kelp_block";
|
||||
public const DRIPSTONE_BLOCK = "minecraft:dripstone_block";
|
||||
public const DROPPER = "minecraft:dropper";
|
||||
@ -474,6 +508,7 @@ final class BlockTypeNames{
|
||||
public const ELEMENT_97 = "minecraft:element_97";
|
||||
public const ELEMENT_98 = "minecraft:element_98";
|
||||
public const ELEMENT_99 = "minecraft:element_99";
|
||||
public const ELEMENT_CONSTRUCTOR = "minecraft:element_constructor";
|
||||
public const EMERALD_BLOCK = "minecraft:emerald_block";
|
||||
public const EMERALD_ORE = "minecraft:emerald_ore";
|
||||
public const ENCHANTING_TABLE = "minecraft:enchanting_table";
|
||||
@ -484,6 +519,9 @@ final class BlockTypeNames{
|
||||
public const END_PORTAL_FRAME = "minecraft:end_portal_frame";
|
||||
public const END_ROD = "minecraft:end_rod";
|
||||
public const END_STONE = "minecraft:end_stone";
|
||||
public const END_STONE_BRICK_DOUBLE_SLAB = "minecraft:end_stone_brick_double_slab";
|
||||
public const END_STONE_BRICK_SLAB = "minecraft:end_stone_brick_slab";
|
||||
public const END_STONE_BRICK_WALL = "minecraft:end_stone_brick_wall";
|
||||
public const ENDER_CHEST = "minecraft:ender_chest";
|
||||
public const EXPOSED_CHISELED_COPPER = "minecraft:exposed_chiseled_copper";
|
||||
public const EXPOSED_COPPER = "minecraft:exposed_copper";
|
||||
@ -502,6 +540,7 @@ final class BlockTypeNames{
|
||||
public const FIRE_CORAL = "minecraft:fire_coral";
|
||||
public const FIRE_CORAL_BLOCK = "minecraft:fire_coral_block";
|
||||
public const FIRE_CORAL_FAN = "minecraft:fire_coral_fan";
|
||||
public const FIRE_CORAL_WALL_FAN = "minecraft:fire_coral_wall_fan";
|
||||
public const FLETCHING_TABLE = "minecraft:fletching_table";
|
||||
public const FLOWER_POT = "minecraft:flower_pot";
|
||||
public const FLOWERING_AZALEA = "minecraft:flowering_azalea";
|
||||
@ -522,7 +561,10 @@ final class BlockTypeNames{
|
||||
public const GOLD_ORE = "minecraft:gold_ore";
|
||||
public const GOLDEN_RAIL = "minecraft:golden_rail";
|
||||
public const GRANITE = "minecraft:granite";
|
||||
public const GRANITE_DOUBLE_SLAB = "minecraft:granite_double_slab";
|
||||
public const GRANITE_SLAB = "minecraft:granite_slab";
|
||||
public const GRANITE_STAIRS = "minecraft:granite_stairs";
|
||||
public const GRANITE_WALL = "minecraft:granite_wall";
|
||||
public const GRASS_BLOCK = "minecraft:grass_block";
|
||||
public const GRASS_PATH = "minecraft:grass_path";
|
||||
public const GRAVEL = "minecraft:gravel";
|
||||
@ -594,8 +636,15 @@ final class BlockTypeNames{
|
||||
public const HORN_CORAL = "minecraft:horn_coral";
|
||||
public const HORN_CORAL_BLOCK = "minecraft:horn_coral_block";
|
||||
public const HORN_CORAL_FAN = "minecraft:horn_coral_fan";
|
||||
public const HORN_CORAL_WALL_FAN = "minecraft:horn_coral_wall_fan";
|
||||
public const ICE = "minecraft:ice";
|
||||
public const INFESTED_CHISELED_STONE_BRICKS = "minecraft:infested_chiseled_stone_bricks";
|
||||
public const INFESTED_COBBLESTONE = "minecraft:infested_cobblestone";
|
||||
public const INFESTED_CRACKED_STONE_BRICKS = "minecraft:infested_cracked_stone_bricks";
|
||||
public const INFESTED_DEEPSLATE = "minecraft:infested_deepslate";
|
||||
public const INFESTED_MOSSY_STONE_BRICKS = "minecraft:infested_mossy_stone_bricks";
|
||||
public const INFESTED_STONE = "minecraft:infested_stone";
|
||||
public const INFESTED_STONE_BRICKS = "minecraft:infested_stone_bricks";
|
||||
public const INFO_UPDATE = "minecraft:info_update";
|
||||
public const INFO_UPDATE2 = "minecraft:info_update2";
|
||||
public const INVISIBLE_BEDROCK = "minecraft:invisible_bedrock";
|
||||
@ -624,6 +673,7 @@ final class BlockTypeNames{
|
||||
public const JUNGLE_WALL_SIGN = "minecraft:jungle_wall_sign";
|
||||
public const JUNGLE_WOOD = "minecraft:jungle_wood";
|
||||
public const KELP = "minecraft:kelp";
|
||||
public const LAB_TABLE = "minecraft:lab_table";
|
||||
public const LADDER = "minecraft:ladder";
|
||||
public const LANTERN = "minecraft:lantern";
|
||||
public const LAPIS_BLOCK = "minecraft:lapis_block";
|
||||
@ -633,7 +683,22 @@ final class BlockTypeNames{
|
||||
public const LAVA = "minecraft:lava";
|
||||
public const LECTERN = "minecraft:lectern";
|
||||
public const LEVER = "minecraft:lever";
|
||||
public const LIGHT_BLOCK = "minecraft:light_block";
|
||||
public const LIGHT_BLOCK_0 = "minecraft:light_block_0";
|
||||
public const LIGHT_BLOCK_1 = "minecraft:light_block_1";
|
||||
public const LIGHT_BLOCK_10 = "minecraft:light_block_10";
|
||||
public const LIGHT_BLOCK_11 = "minecraft:light_block_11";
|
||||
public const LIGHT_BLOCK_12 = "minecraft:light_block_12";
|
||||
public const LIGHT_BLOCK_13 = "minecraft:light_block_13";
|
||||
public const LIGHT_BLOCK_14 = "minecraft:light_block_14";
|
||||
public const LIGHT_BLOCK_15 = "minecraft:light_block_15";
|
||||
public const LIGHT_BLOCK_2 = "minecraft:light_block_2";
|
||||
public const LIGHT_BLOCK_3 = "minecraft:light_block_3";
|
||||
public const LIGHT_BLOCK_4 = "minecraft:light_block_4";
|
||||
public const LIGHT_BLOCK_5 = "minecraft:light_block_5";
|
||||
public const LIGHT_BLOCK_6 = "minecraft:light_block_6";
|
||||
public const LIGHT_BLOCK_7 = "minecraft:light_block_7";
|
||||
public const LIGHT_BLOCK_8 = "minecraft:light_block_8";
|
||||
public const LIGHT_BLOCK_9 = "minecraft:light_block_9";
|
||||
public const LIGHT_BLUE_CANDLE = "minecraft:light_blue_candle";
|
||||
public const LIGHT_BLUE_CANDLE_CAKE = "minecraft:light_blue_candle_cake";
|
||||
public const LIGHT_BLUE_CARPET = "minecraft:light_blue_carpet";
|
||||
@ -709,16 +774,23 @@ final class BlockTypeNames{
|
||||
public const MANGROVE_TRAPDOOR = "minecraft:mangrove_trapdoor";
|
||||
public const MANGROVE_WALL_SIGN = "minecraft:mangrove_wall_sign";
|
||||
public const MANGROVE_WOOD = "minecraft:mangrove_wood";
|
||||
public const MATERIAL_REDUCER = "minecraft:material_reducer";
|
||||
public const MEDIUM_AMETHYST_BUD = "minecraft:medium_amethyst_bud";
|
||||
public const MELON_BLOCK = "minecraft:melon_block";
|
||||
public const MELON_STEM = "minecraft:melon_stem";
|
||||
public const MOB_SPAWNER = "minecraft:mob_spawner";
|
||||
public const MONSTER_EGG = "minecraft:monster_egg";
|
||||
public const MOSS_BLOCK = "minecraft:moss_block";
|
||||
public const MOSS_CARPET = "minecraft:moss_carpet";
|
||||
public const MOSSY_COBBLESTONE = "minecraft:mossy_cobblestone";
|
||||
public const MOSSY_COBBLESTONE_DOUBLE_SLAB = "minecraft:mossy_cobblestone_double_slab";
|
||||
public const MOSSY_COBBLESTONE_SLAB = "minecraft:mossy_cobblestone_slab";
|
||||
public const MOSSY_COBBLESTONE_STAIRS = "minecraft:mossy_cobblestone_stairs";
|
||||
public const MOSSY_COBBLESTONE_WALL = "minecraft:mossy_cobblestone_wall";
|
||||
public const MOSSY_STONE_BRICK_DOUBLE_SLAB = "minecraft:mossy_stone_brick_double_slab";
|
||||
public const MOSSY_STONE_BRICK_SLAB = "minecraft:mossy_stone_brick_slab";
|
||||
public const MOSSY_STONE_BRICK_STAIRS = "minecraft:mossy_stone_brick_stairs";
|
||||
public const MOSSY_STONE_BRICK_WALL = "minecraft:mossy_stone_brick_wall";
|
||||
public const MOSSY_STONE_BRICKS = "minecraft:mossy_stone_bricks";
|
||||
public const MOVING_BLOCK = "minecraft:moving_block";
|
||||
public const MUD = "minecraft:mud";
|
||||
public const MUD_BRICK_DOUBLE_SLAB = "minecraft:mud_brick_double_slab";
|
||||
@ -727,11 +799,14 @@ final class BlockTypeNames{
|
||||
public const MUD_BRICK_WALL = "minecraft:mud_brick_wall";
|
||||
public const MUD_BRICKS = "minecraft:mud_bricks";
|
||||
public const MUDDY_MANGROVE_ROOTS = "minecraft:muddy_mangrove_roots";
|
||||
public const MUSHROOM_STEM = "minecraft:mushroom_stem";
|
||||
public const MYCELIUM = "minecraft:mycelium";
|
||||
public const NETHER_BRICK = "minecraft:nether_brick";
|
||||
public const NETHER_BRICK_DOUBLE_SLAB = "minecraft:nether_brick_double_slab";
|
||||
public const NETHER_BRICK_FENCE = "minecraft:nether_brick_fence";
|
||||
public const NETHER_BRICK_SLAB = "minecraft:nether_brick_slab";
|
||||
public const NETHER_BRICK_STAIRS = "minecraft:nether_brick_stairs";
|
||||
public const NETHER_BRICK_WALL = "minecraft:nether_brick_wall";
|
||||
public const NETHER_GOLD_ORE = "minecraft:nether_gold_ore";
|
||||
public const NETHER_SPROUTS = "minecraft:nether_sprouts";
|
||||
public const NETHER_WART = "minecraft:nether_wart";
|
||||
@ -739,6 +814,8 @@ final class BlockTypeNames{
|
||||
public const NETHERITE_BLOCK = "minecraft:netherite_block";
|
||||
public const NETHERRACK = "minecraft:netherrack";
|
||||
public const NETHERREACTOR = "minecraft:netherreactor";
|
||||
public const NORMAL_STONE_DOUBLE_SLAB = "minecraft:normal_stone_double_slab";
|
||||
public const NORMAL_STONE_SLAB = "minecraft:normal_stone_slab";
|
||||
public const NORMAL_STONE_STAIRS = "minecraft:normal_stone_stairs";
|
||||
public const NOTEBLOCK = "minecraft:noteblock";
|
||||
public const OAK_DOUBLE_SLAB = "minecraft:oak_double_slab";
|
||||
@ -781,7 +858,9 @@ final class BlockTypeNames{
|
||||
public const PACKED_MUD = "minecraft:packed_mud";
|
||||
public const PEARLESCENT_FROGLIGHT = "minecraft:pearlescent_froglight";
|
||||
public const PEONY = "minecraft:peony";
|
||||
public const PETRIFIED_OAK_DOUBLE_SLAB = "minecraft:petrified_oak_double_slab";
|
||||
public const PETRIFIED_OAK_SLAB = "minecraft:petrified_oak_slab";
|
||||
public const PIGLIN_HEAD = "minecraft:piglin_head";
|
||||
public const PINK_CANDLE = "minecraft:pink_candle";
|
||||
public const PINK_CANDLE_CAKE = "minecraft:pink_candle_cake";
|
||||
public const PINK_CARPET = "minecraft:pink_carpet";
|
||||
@ -799,9 +878,12 @@ 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 PLAYER_HEAD = "minecraft:player_head";
|
||||
public const PODZOL = "minecraft:podzol";
|
||||
public const POINTED_DRIPSTONE = "minecraft:pointed_dripstone";
|
||||
public const POLISHED_ANDESITE = "minecraft:polished_andesite";
|
||||
public const POLISHED_ANDESITE_DOUBLE_SLAB = "minecraft:polished_andesite_double_slab";
|
||||
public const POLISHED_ANDESITE_SLAB = "minecraft:polished_andesite_slab";
|
||||
public const POLISHED_ANDESITE_STAIRS = "minecraft:polished_andesite_stairs";
|
||||
public const POLISHED_BASALT = "minecraft:polished_basalt";
|
||||
public const POLISHED_BLACKSTONE = "minecraft:polished_blackstone";
|
||||
@ -822,8 +904,12 @@ final class BlockTypeNames{
|
||||
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_DOUBLE_SLAB = "minecraft:polished_diorite_double_slab";
|
||||
public const POLISHED_DIORITE_SLAB = "minecraft:polished_diorite_slab";
|
||||
public const POLISHED_DIORITE_STAIRS = "minecraft:polished_diorite_stairs";
|
||||
public const POLISHED_GRANITE = "minecraft:polished_granite";
|
||||
public const POLISHED_GRANITE_DOUBLE_SLAB = "minecraft:polished_granite_double_slab";
|
||||
public const POLISHED_GRANITE_SLAB = "minecraft:polished_granite_slab";
|
||||
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";
|
||||
@ -837,8 +923,14 @@ final class BlockTypeNames{
|
||||
public const POWERED_COMPARATOR = "minecraft:powered_comparator";
|
||||
public const POWERED_REPEATER = "minecraft:powered_repeater";
|
||||
public const PRISMARINE = "minecraft:prismarine";
|
||||
public const PRISMARINE_BRICK_DOUBLE_SLAB = "minecraft:prismarine_brick_double_slab";
|
||||
public const PRISMARINE_BRICK_SLAB = "minecraft:prismarine_brick_slab";
|
||||
public const PRISMARINE_BRICKS = "minecraft:prismarine_bricks";
|
||||
public const PRISMARINE_BRICKS_STAIRS = "minecraft:prismarine_bricks_stairs";
|
||||
public const PRISMARINE_DOUBLE_SLAB = "minecraft:prismarine_double_slab";
|
||||
public const PRISMARINE_SLAB = "minecraft:prismarine_slab";
|
||||
public const PRISMARINE_STAIRS = "minecraft:prismarine_stairs";
|
||||
public const PRISMARINE_WALL = "minecraft:prismarine_wall";
|
||||
public const PUMPKIN = "minecraft:pumpkin";
|
||||
public const PUMPKIN_STEM = "minecraft:pumpkin_stem";
|
||||
public const PURPLE_CANDLE = "minecraft:purple_candle";
|
||||
@ -853,10 +945,15 @@ final class BlockTypeNames{
|
||||
public const PURPLE_TERRACOTTA = "minecraft:purple_terracotta";
|
||||
public const PURPLE_WOOL = "minecraft:purple_wool";
|
||||
public const PURPUR_BLOCK = "minecraft:purpur_block";
|
||||
public const PURPUR_DOUBLE_SLAB = "minecraft:purpur_double_slab";
|
||||
public const PURPUR_PILLAR = "minecraft:purpur_pillar";
|
||||
public const PURPUR_SLAB = "minecraft:purpur_slab";
|
||||
public const PURPUR_STAIRS = "minecraft:purpur_stairs";
|
||||
public const QUARTZ_BLOCK = "minecraft:quartz_block";
|
||||
public const QUARTZ_BRICKS = "minecraft:quartz_bricks";
|
||||
public const QUARTZ_DOUBLE_SLAB = "minecraft:quartz_double_slab";
|
||||
public const QUARTZ_ORE = "minecraft:quartz_ore";
|
||||
public const QUARTZ_PILLAR = "minecraft:quartz_pillar";
|
||||
public const QUARTZ_SLAB = "minecraft:quartz_slab";
|
||||
public const QUARTZ_STAIRS = "minecraft:quartz_stairs";
|
||||
public const RAIL = "minecraft:rail";
|
||||
@ -872,9 +969,16 @@ final class BlockTypeNames{
|
||||
public const RED_MUSHROOM = "minecraft:red_mushroom";
|
||||
public const RED_MUSHROOM_BLOCK = "minecraft:red_mushroom_block";
|
||||
public const RED_NETHER_BRICK = "minecraft:red_nether_brick";
|
||||
public const RED_NETHER_BRICK_DOUBLE_SLAB = "minecraft:red_nether_brick_double_slab";
|
||||
public const RED_NETHER_BRICK_SLAB = "minecraft:red_nether_brick_slab";
|
||||
public const RED_NETHER_BRICK_STAIRS = "minecraft:red_nether_brick_stairs";
|
||||
public const RED_NETHER_BRICK_WALL = "minecraft:red_nether_brick_wall";
|
||||
public const RED_SAND = "minecraft:red_sand";
|
||||
public const RED_SANDSTONE = "minecraft:red_sandstone";
|
||||
public const RED_SANDSTONE_DOUBLE_SLAB = "minecraft:red_sandstone_double_slab";
|
||||
public const RED_SANDSTONE_SLAB = "minecraft:red_sandstone_slab";
|
||||
public const RED_SANDSTONE_STAIRS = "minecraft:red_sandstone_stairs";
|
||||
public const RED_SANDSTONE_WALL = "minecraft:red_sandstone_wall";
|
||||
public const RED_SHULKER_BOX = "minecraft:red_shulker_box";
|
||||
public const RED_STAINED_GLASS = "minecraft:red_stained_glass";
|
||||
public const RED_STAINED_GLASS_PANE = "minecraft:red_stained_glass_pane";
|
||||
@ -894,8 +998,10 @@ final class BlockTypeNames{
|
||||
public const ROSE_BUSH = "minecraft:rose_bush";
|
||||
public const SAND = "minecraft:sand";
|
||||
public const SANDSTONE = "minecraft:sandstone";
|
||||
public const SANDSTONE_DOUBLE_SLAB = "minecraft:sandstone_double_slab";
|
||||
public const SANDSTONE_SLAB = "minecraft:sandstone_slab";
|
||||
public const SANDSTONE_STAIRS = "minecraft:sandstone_stairs";
|
||||
public const SANDSTONE_WALL = "minecraft:sandstone_wall";
|
||||
public const SCAFFOLDING = "minecraft:scaffolding";
|
||||
public const SCULK = "minecraft:sculk";
|
||||
public const SCULK_CATALYST = "minecraft:sculk_catalyst";
|
||||
@ -908,17 +1014,27 @@ final class BlockTypeNames{
|
||||
public const SHORT_GRASS = "minecraft:short_grass";
|
||||
public const SHROOMLIGHT = "minecraft:shroomlight";
|
||||
public const SILVER_GLAZED_TERRACOTTA = "minecraft:silver_glazed_terracotta";
|
||||
public const SKULL = "minecraft:skull";
|
||||
public const SKELETON_SKULL = "minecraft:skeleton_skull";
|
||||
public const SLIME = "minecraft:slime";
|
||||
public const SMALL_AMETHYST_BUD = "minecraft:small_amethyst_bud";
|
||||
public const SMALL_DRIPLEAF_BLOCK = "minecraft:small_dripleaf_block";
|
||||
public const SMITHING_TABLE = "minecraft:smithing_table";
|
||||
public const SMOKER = "minecraft:smoker";
|
||||
public const SMOOTH_BASALT = "minecraft:smooth_basalt";
|
||||
public const SMOOTH_QUARTZ = "minecraft:smooth_quartz";
|
||||
public const SMOOTH_QUARTZ_DOUBLE_SLAB = "minecraft:smooth_quartz_double_slab";
|
||||
public const SMOOTH_QUARTZ_SLAB = "minecraft:smooth_quartz_slab";
|
||||
public const SMOOTH_QUARTZ_STAIRS = "minecraft:smooth_quartz_stairs";
|
||||
public const SMOOTH_RED_SANDSTONE = "minecraft:smooth_red_sandstone";
|
||||
public const SMOOTH_RED_SANDSTONE_DOUBLE_SLAB = "minecraft:smooth_red_sandstone_double_slab";
|
||||
public const SMOOTH_RED_SANDSTONE_SLAB = "minecraft:smooth_red_sandstone_slab";
|
||||
public const SMOOTH_RED_SANDSTONE_STAIRS = "minecraft:smooth_red_sandstone_stairs";
|
||||
public const SMOOTH_SANDSTONE = "minecraft:smooth_sandstone";
|
||||
public const SMOOTH_SANDSTONE_DOUBLE_SLAB = "minecraft:smooth_sandstone_double_slab";
|
||||
public const SMOOTH_SANDSTONE_SLAB = "minecraft:smooth_sandstone_slab";
|
||||
public const SMOOTH_SANDSTONE_STAIRS = "minecraft:smooth_sandstone_stairs";
|
||||
public const SMOOTH_STONE = "minecraft:smooth_stone";
|
||||
public const SMOOTH_STONE_DOUBLE_SLAB = "minecraft:smooth_stone_double_slab";
|
||||
public const SMOOTH_STONE_SLAB = "minecraft:smooth_stone_slab";
|
||||
public const SNIFFER_EGG = "minecraft:sniffer_egg";
|
||||
public const SNOW = "minecraft:snow";
|
||||
@ -953,15 +1069,14 @@ final class BlockTypeNames{
|
||||
public const STICKY_PISTON = "minecraft:sticky_piston";
|
||||
public const STICKY_PISTON_ARM_COLLISION = "minecraft:sticky_piston_arm_collision";
|
||||
public const STONE = "minecraft:stone";
|
||||
public const STONE_BLOCK_SLAB2 = "minecraft:stone_block_slab2";
|
||||
public const STONE_BLOCK_SLAB3 = "minecraft:stone_block_slab3";
|
||||
public const STONE_BLOCK_SLAB4 = "minecraft:stone_block_slab4";
|
||||
public const STONE_BRICK_DOUBLE_SLAB = "minecraft:stone_brick_double_slab";
|
||||
public const STONE_BRICK_SLAB = "minecraft:stone_brick_slab";
|
||||
public const STONE_BRICK_STAIRS = "minecraft:stone_brick_stairs";
|
||||
public const STONE_BRICK_WALL = "minecraft:stone_brick_wall";
|
||||
public const STONE_BRICKS = "minecraft:stone_bricks";
|
||||
public const STONE_BUTTON = "minecraft:stone_button";
|
||||
public const STONE_PRESSURE_PLATE = "minecraft:stone_pressure_plate";
|
||||
public const STONE_STAIRS = "minecraft:stone_stairs";
|
||||
public const STONEBRICK = "minecraft:stonebrick";
|
||||
public const STONECUTTER = "minecraft:stonecutter";
|
||||
public const STONECUTTER_BLOCK = "minecraft:stonecutter_block";
|
||||
public const STRIPPED_ACACIA_LOG = "minecraft:stripped_acacia_log";
|
||||
@ -1006,6 +1121,7 @@ final class BlockTypeNames{
|
||||
public const TUBE_CORAL = "minecraft:tube_coral";
|
||||
public const TUBE_CORAL_BLOCK = "minecraft:tube_coral_block";
|
||||
public const TUBE_CORAL_FAN = "minecraft:tube_coral_fan";
|
||||
public const TUBE_CORAL_WALL_FAN = "minecraft:tube_coral_wall_fan";
|
||||
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";
|
||||
@ -1018,6 +1134,7 @@ final class BlockTypeNames{
|
||||
public const TUFF_WALL = "minecraft:tuff_wall";
|
||||
public const TURTLE_EGG = "minecraft:turtle_egg";
|
||||
public const TWISTING_VINES = "minecraft:twisting_vines";
|
||||
public const UNDERWATER_TNT = "minecraft:underwater_tnt";
|
||||
public const UNDERWATER_TORCH = "minecraft:underwater_torch";
|
||||
public const UNDYED_SHULKER_BOX = "minecraft:undyed_shulker_box";
|
||||
public const UNKNOWN = "minecraft:unknown";
|
||||
@ -1102,6 +1219,7 @@ final class BlockTypeNames{
|
||||
public const WEATHERED_DOUBLE_CUT_COPPER_SLAB = "minecraft:weathered_double_cut_copper_slab";
|
||||
public const WEB = "minecraft:web";
|
||||
public const WEEPING_VINES = "minecraft:weeping_vines";
|
||||
public const WET_SPONGE = "minecraft:wet_sponge";
|
||||
public const WHEAT = "minecraft:wheat";
|
||||
public const WHITE_CANDLE = "minecraft:white_candle";
|
||||
public const WHITE_CANDLE_CAKE = "minecraft:white_candle_cake";
|
||||
@ -1116,6 +1234,7 @@ final class BlockTypeNames{
|
||||
public const WHITE_TULIP = "minecraft:white_tulip";
|
||||
public const WHITE_WOOL = "minecraft:white_wool";
|
||||
public const WITHER_ROSE = "minecraft:wither_rose";
|
||||
public const WITHER_SKELETON_SKULL = "minecraft:wither_skeleton_skull";
|
||||
public const WOODEN_BUTTON = "minecraft:wooden_button";
|
||||
public const WOODEN_DOOR = "minecraft:wooden_door";
|
||||
public const WOODEN_PRESSURE_PLATE = "minecraft:wooden_pressure_plate";
|
||||
@ -1124,11 +1243,11 @@ final class BlockTypeNames{
|
||||
public const YELLOW_CARPET = "minecraft:yellow_carpet";
|
||||
public const YELLOW_CONCRETE = "minecraft:yellow_concrete";
|
||||
public const YELLOW_CONCRETE_POWDER = "minecraft:yellow_concrete_powder";
|
||||
public const YELLOW_FLOWER = "minecraft:yellow_flower";
|
||||
public const YELLOW_GLAZED_TERRACOTTA = "minecraft:yellow_glazed_terracotta";
|
||||
public const YELLOW_SHULKER_BOX = "minecraft:yellow_shulker_box";
|
||||
public const YELLOW_STAINED_GLASS = "minecraft:yellow_stained_glass";
|
||||
public const YELLOW_STAINED_GLASS_PANE = "minecraft:yellow_stained_glass_pane";
|
||||
public const YELLOW_TERRACOTTA = "minecraft:yellow_terracotta";
|
||||
public const YELLOW_WOOL = "minecraft:yellow_wool";
|
||||
public const ZOMBIE_HEAD = "minecraft:zombie_head";
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ use pocketmine\block\Cactus;
|
||||
use pocketmine\block\Cake;
|
||||
use pocketmine\block\CakeWithCandle;
|
||||
use pocketmine\block\CakeWithDyedCandle;
|
||||
use pocketmine\block\Campfire;
|
||||
use pocketmine\block\Candle;
|
||||
use pocketmine\block\Carpet;
|
||||
use pocketmine\block\Carrot;
|
||||
@ -57,8 +58,12 @@ use pocketmine\block\CocoaBlock;
|
||||
use pocketmine\block\Concrete;
|
||||
use pocketmine\block\ConcretePowder;
|
||||
use pocketmine\block\Copper;
|
||||
use pocketmine\block\CopperBulb;
|
||||
use pocketmine\block\CopperDoor;
|
||||
use pocketmine\block\CopperGrate;
|
||||
use pocketmine\block\CopperSlab;
|
||||
use pocketmine\block\CopperStairs;
|
||||
use pocketmine\block\CopperTrapdoor;
|
||||
use pocketmine\block\Coral;
|
||||
use pocketmine\block\CoralBlock;
|
||||
use pocketmine\block\DaylightSensor;
|
||||
@ -124,6 +129,7 @@ use pocketmine\block\SimplePressurePlate;
|
||||
use pocketmine\block\Slab;
|
||||
use pocketmine\block\SmallDripleaf;
|
||||
use pocketmine\block\SnowLayer;
|
||||
use pocketmine\block\SoulCampfire;
|
||||
use pocketmine\block\Sponge;
|
||||
use pocketmine\block\StainedGlass;
|
||||
use pocketmine\block\StainedGlassPane;
|
||||
@ -151,6 +157,7 @@ use pocketmine\block\utils\DripleafState;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\block\utils\FroglightType;
|
||||
use pocketmine\block\utils\LeverFacing;
|
||||
use pocketmine\block\utils\MobHeadType;
|
||||
use pocketmine\block\VanillaBlocks as Blocks;
|
||||
use pocketmine\block\Vine;
|
||||
use pocketmine\block\Wall;
|
||||
@ -205,6 +212,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->registerFlatWoodBlockSerializers();
|
||||
$this->registerLeavesSerializers();
|
||||
$this->registerSaplingSerializers();
|
||||
$this->registerMobHeadSerializers();
|
||||
$this->registerSimpleSerializers();
|
||||
$this->registerSerializers();
|
||||
}
|
||||
@ -562,6 +570,17 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
CoralType::TUBE => $block->isDead() ? Ids::DEAD_TUBE_CORAL_BLOCK : Ids::TUBE_CORAL_BLOCK,
|
||||
}
|
||||
));
|
||||
|
||||
$this->map(Blocks::WALL_CORAL_FAN(), fn(WallCoralFan $block) => Writer::create(
|
||||
match($block->getCoralType()){
|
||||
CoralType::TUBE => $block->isDead() ? Ids::DEAD_TUBE_CORAL_WALL_FAN : Ids::TUBE_CORAL_WALL_FAN,
|
||||
CoralType::BRAIN => $block->isDead() ? Ids::DEAD_BRAIN_CORAL_WALL_FAN : Ids::BRAIN_CORAL_WALL_FAN,
|
||||
CoralType::BUBBLE => $block->isDead() ? Ids::DEAD_BUBBLE_CORAL_WALL_FAN : Ids::BUBBLE_CORAL_WALL_FAN,
|
||||
CoralType::FIRE => $block->isDead() ? Ids::DEAD_FIRE_CORAL_WALL_FAN : Ids::FIRE_CORAL_WALL_FAN,
|
||||
CoralType::HORN => $block->isDead() ? Ids::DEAD_HORN_CORAL_WALL_FAN : Ids::HORN_CORAL_WALL_FAN,
|
||||
})
|
||||
->writeCoralFacing($block->getFacing())
|
||||
);
|
||||
}
|
||||
|
||||
private function registerCauldronSerializers() : void{
|
||||
@ -613,17 +632,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::CHERRY_PLANKS(), Ids::CHERRY_PLANKS);
|
||||
$this->mapSlab(Blocks::CHERRY_SLAB(), Ids::CHERRY_SLAB, Ids::CHERRY_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::CHERRY_STAIRS(), Ids::CHERRY_STAIRS);
|
||||
$this->map(Blocks::CHERRY_WOOD(), function(Wood $block) : Writer{
|
||||
//we can't use the standard method for this because cherry_wood has a useless property attached to it
|
||||
if(!$block->isStripped()){
|
||||
return Writer::create(Ids::CHERRY_WOOD)
|
||||
->writePillarAxis($block->getAxis())
|
||||
->writeBool(StateNames::STRIPPED_BIT, false); //this is useless, but it has to be written
|
||||
}else{
|
||||
return Writer::create(Ids::STRIPPED_CHERRY_WOOD)
|
||||
->writePillarAxis($block->getAxis());
|
||||
}
|
||||
});
|
||||
$this->mapLog(Blocks::CHERRY_WOOD(), Ids::CHERRY_WOOD, Ids::STRIPPED_CHERRY_WOOD);
|
||||
|
||||
$this->map(Blocks::CRIMSON_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::CRIMSON_BUTTON)));
|
||||
$this->map(Blocks::CRIMSON_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::CRIMSON_DOOR)));
|
||||
@ -679,17 +688,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::MANGROVE_PLANKS(), Ids::MANGROVE_PLANKS);
|
||||
$this->mapSlab(Blocks::MANGROVE_SLAB(), Ids::MANGROVE_SLAB, Ids::MANGROVE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::MANGROVE_STAIRS(), Ids::MANGROVE_STAIRS);
|
||||
$this->map(Blocks::MANGROVE_WOOD(), function(Wood $block) : Writer{
|
||||
//we can't use the standard method for this because mangrove_wood has a useless property attached to it
|
||||
if(!$block->isStripped()){
|
||||
return Writer::create(Ids::MANGROVE_WOOD)
|
||||
->writePillarAxis($block->getAxis())
|
||||
->writeBool(StateNames::STRIPPED_BIT, false); //this is useless, but it has to be written
|
||||
}else{
|
||||
return Writer::create(Ids::STRIPPED_MANGROVE_WOOD)
|
||||
->writePillarAxis($block->getAxis());
|
||||
}
|
||||
});
|
||||
$this->mapLog(Blocks::MANGROVE_WOOD(), Ids::MANGROVE_WOOD, Ids::STRIPPED_MANGROVE_WOOD);
|
||||
|
||||
$this->map(Blocks::OAK_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::WOODEN_BUTTON)));
|
||||
$this->map(Blocks::OAK_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::WOODEN_DOOR)));
|
||||
@ -764,6 +763,18 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
}
|
||||
}
|
||||
|
||||
private function registerMobHeadSerializers() : void{
|
||||
$this->map(Blocks::MOB_HEAD(), fn(MobHead $block) => Writer::create(match ($block->getMobHeadType()){
|
||||
MobHeadType::CREEPER => Ids::CREEPER_HEAD,
|
||||
MobHeadType::DRAGON => Ids::DRAGON_HEAD,
|
||||
MobHeadType::PIGLIN => Ids::PIGLIN_HEAD,
|
||||
MobHeadType::PLAYER => Ids::PLAYER_HEAD,
|
||||
MobHeadType::SKELETON => Ids::SKELETON_SKULL,
|
||||
MobHeadType::WITHER_SKELETON => Ids::WITHER_SKELETON_SKULL,
|
||||
MobHeadType::ZOMBIE => Ids::ZOMBIE_HEAD,
|
||||
})->writeFacingWithoutDown($block->getFacing()));
|
||||
}
|
||||
|
||||
private function registerSimpleSerializers() : void{
|
||||
$this->mapSimple(Blocks::AIR(), Ids::AIR);
|
||||
$this->mapSimple(Blocks::AMETHYST(), Ids::AMETHYST_BLOCK);
|
||||
@ -783,6 +794,11 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::CHISELED_DEEPSLATE(), Ids::CHISELED_DEEPSLATE);
|
||||
$this->mapSimple(Blocks::CHISELED_NETHER_BRICKS(), Ids::CHISELED_NETHER_BRICKS);
|
||||
$this->mapSimple(Blocks::CHISELED_POLISHED_BLACKSTONE(), Ids::CHISELED_POLISHED_BLACKSTONE);
|
||||
$this->mapSimple(Blocks::CHISELED_RED_SANDSTONE(), Ids::CHISELED_RED_SANDSTONE);
|
||||
$this->mapSimple(Blocks::CHISELED_SANDSTONE(), Ids::CHISELED_SANDSTONE);
|
||||
$this->mapSimple(Blocks::CHISELED_STONE_BRICKS(), Ids::CHISELED_STONE_BRICKS);
|
||||
$this->mapSimple(Blocks::CHISELED_TUFF(), Ids::CHISELED_TUFF);
|
||||
$this->mapSimple(Blocks::CHISELED_TUFF_BRICKS(), Ids::CHISELED_TUFF_BRICKS);
|
||||
$this->mapSimple(Blocks::CHORUS_PLANT(), Ids::CHORUS_PLANT);
|
||||
$this->mapSimple(Blocks::CLAY(), Ids::CLAY);
|
||||
$this->mapSimple(Blocks::COAL(), Ids::COAL_BLOCK);
|
||||
@ -795,10 +811,14 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::CRACKED_DEEPSLATE_TILES(), Ids::CRACKED_DEEPSLATE_TILES);
|
||||
$this->mapSimple(Blocks::CRACKED_NETHER_BRICKS(), Ids::CRACKED_NETHER_BRICKS);
|
||||
$this->mapSimple(Blocks::CRACKED_POLISHED_BLACKSTONE_BRICKS(), Ids::CRACKED_POLISHED_BLACKSTONE_BRICKS);
|
||||
$this->mapSimple(Blocks::CRACKED_STONE_BRICKS(), Ids::CRACKED_STONE_BRICKS);
|
||||
$this->mapSimple(Blocks::CRAFTING_TABLE(), Ids::CRAFTING_TABLE);
|
||||
$this->mapSimple(Blocks::CRIMSON_ROOTS(), Ids::CRIMSON_ROOTS);
|
||||
$this->mapSimple(Blocks::CRYING_OBSIDIAN(), Ids::CRYING_OBSIDIAN);
|
||||
$this->mapSimple(Blocks::DANDELION(), Ids::YELLOW_FLOWER);
|
||||
$this->mapSimple(Blocks::DANDELION(), Ids::DANDELION);
|
||||
$this->mapSimple(Blocks::CUT_RED_SANDSTONE(), Ids::CUT_RED_SANDSTONE);
|
||||
$this->mapSimple(Blocks::CUT_SANDSTONE(), Ids::CUT_SANDSTONE);
|
||||
$this->mapSimple(Blocks::DARK_PRISMARINE(), Ids::DARK_PRISMARINE);
|
||||
$this->mapSimple(Blocks::DEAD_BUSH(), Ids::DEADBUSH);
|
||||
$this->mapSimple(Blocks::DEEPSLATE_BRICKS(), Ids::DEEPSLATE_BRICKS);
|
||||
$this->mapSimple(Blocks::DEEPSLATE_COAL_ORE(), Ids::DEEPSLATE_COAL_ORE);
|
||||
@ -957,6 +977,12 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::HARDENED_GLASS_PANE(), Ids::HARD_GLASS_PANE);
|
||||
$this->mapSimple(Blocks::HONEYCOMB(), Ids::HONEYCOMB_BLOCK);
|
||||
$this->mapSimple(Blocks::ICE(), Ids::ICE);
|
||||
$this->mapSimple(Blocks::INFESTED_CHISELED_STONE_BRICK(), Ids::INFESTED_CHISELED_STONE_BRICKS);
|
||||
$this->mapSimple(Blocks::INFESTED_COBBLESTONE(), Ids::INFESTED_COBBLESTONE);
|
||||
$this->mapSimple(Blocks::INFESTED_CRACKED_STONE_BRICK(), Ids::INFESTED_CRACKED_STONE_BRICKS);
|
||||
$this->mapSimple(Blocks::INFESTED_MOSSY_STONE_BRICK(), Ids::INFESTED_MOSSY_STONE_BRICKS);
|
||||
$this->mapSimple(Blocks::INFESTED_STONE(), Ids::INFESTED_STONE);
|
||||
$this->mapSimple(Blocks::INFESTED_STONE_BRICK(), Ids::INFESTED_STONE_BRICKS);
|
||||
$this->mapSimple(Blocks::INFO_UPDATE(), Ids::INFO_UPDATE);
|
||||
$this->mapSimple(Blocks::INFO_UPDATE2(), Ids::INFO_UPDATE2);
|
||||
$this->mapSimple(Blocks::INVISIBLE_BEDROCK(), Ids::INVISIBLE_BEDROCK);
|
||||
@ -973,6 +999,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::MELON(), Ids::MELON_BLOCK);
|
||||
$this->mapSimple(Blocks::MONSTER_SPAWNER(), Ids::MOB_SPAWNER);
|
||||
$this->mapSimple(Blocks::MOSSY_COBBLESTONE(), Ids::MOSSY_COBBLESTONE);
|
||||
$this->mapSimple(Blocks::MOSSY_STONE_BRICKS(), Ids::MOSSY_STONE_BRICKS);
|
||||
$this->mapSimple(Blocks::MUD(), Ids::MUD);
|
||||
$this->mapSimple(Blocks::MUD_BRICKS(), Ids::MUD_BRICKS);
|
||||
$this->mapSimple(Blocks::MYCELIUM(), Ids::MYCELIUM);
|
||||
@ -995,6 +1022,9 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$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::POLISHED_TUFF(), Ids::POLISHED_TUFF);
|
||||
$this->mapSimple(Blocks::PRISMARINE(), Ids::PRISMARINE);
|
||||
$this->mapSimple(Blocks::PRISMARINE_BRICKS(), Ids::PRISMARINE_BRICKS);
|
||||
$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);
|
||||
@ -1002,8 +1032,12 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::REDSTONE(), Ids::REDSTONE_BLOCK);
|
||||
$this->mapSimple(Blocks::RED_MUSHROOM(), Ids::RED_MUSHROOM);
|
||||
$this->mapSimple(Blocks::RED_NETHER_BRICKS(), Ids::RED_NETHER_BRICK);
|
||||
$this->mapSimple(Blocks::RED_SAND(), Ids::RED_SAND);
|
||||
$this->mapSimple(Blocks::RED_SANDSTONE(), Ids::RED_SANDSTONE);
|
||||
$this->mapSimple(Blocks::REINFORCED_DEEPSLATE(), Ids::REINFORCED_DEEPSLATE);
|
||||
$this->mapSimple(Blocks::RESERVED6(), Ids::RESERVED6);
|
||||
$this->mapSimple(Blocks::SAND(), Ids::SAND);
|
||||
$this->mapSimple(Blocks::SANDSTONE(), Ids::SANDSTONE);
|
||||
$this->mapSimple(Blocks::SCULK(), Ids::SCULK);
|
||||
$this->mapSimple(Blocks::SEA_LANTERN(), Ids::SEA_LANTERN);
|
||||
$this->mapSimple(Blocks::SHROOMLIGHT(), Ids::SHROOMLIGHT);
|
||||
@ -1011,16 +1045,20 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSimple(Blocks::SLIME(), Ids::SLIME);
|
||||
$this->mapSimple(Blocks::SMITHING_TABLE(), Ids::SMITHING_TABLE);
|
||||
$this->mapSimple(Blocks::SMOOTH_BASALT(), Ids::SMOOTH_BASALT);
|
||||
$this->mapSimple(Blocks::SMOOTH_RED_SANDSTONE(), Ids::SMOOTH_RED_SANDSTONE);
|
||||
$this->mapSimple(Blocks::SMOOTH_SANDSTONE(), Ids::SMOOTH_SANDSTONE);
|
||||
$this->mapSimple(Blocks::SMOOTH_STONE(), Ids::SMOOTH_STONE);
|
||||
$this->mapSimple(Blocks::SNOW(), Ids::SNOW);
|
||||
$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::TALL_GRASS(), Ids::SHORT_GRASS); //no, this is not a typo - tall_grass is now the double block, just to be confusing :(
|
||||
$this->mapSimple(Blocks::STONE_BRICKS(), Ids::STONE_BRICKS);
|
||||
$this->mapSimple(Blocks::TALL_GRASS(), Ids::SHORT_GRASS); //no, this is not a typo - tall_grass is now the double block, just to be confusing :(
|
||||
$this->mapSimple(Blocks::TINTED_GLASS(), Ids::TINTED_GLASS);
|
||||
$this->mapSimple(Blocks::TORCHFLOWER(), Ids::TORCHFLOWER);
|
||||
$this->mapSimple(Blocks::TUFF(), Ids::TUFF);
|
||||
$this->mapSimple(Blocks::TUFF_BRICKS(), Ids::TUFF_BRICKS);
|
||||
$this->mapSimple(Blocks::WARPED_WART_BLOCK(), Ids::WARPED_WART_BLOCK);
|
||||
$this->mapSimple(Blocks::WARPED_ROOTS(), Ids::WARPED_ROOTS);
|
||||
$this->mapSimple(Blocks::WITHER_ROSE(), Ids::WITHER_ROSE);
|
||||
@ -1044,7 +1082,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeBool(StateNames::RAIL_DATA_BIT, $block->isPowered())
|
||||
->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
|
||||
});
|
||||
$this->map(Blocks::ALL_SIDED_MUSHROOM_STEM(), fn() => Writer::create(Ids::BROWN_MUSHROOM_BLOCK)
|
||||
$this->map(Blocks::ALL_SIDED_MUSHROOM_STEM(), fn() => Writer::create(Ids::MUSHROOM_STEM)
|
||||
->writeInt(StateNames::HUGE_MUSHROOM_BITS, BlockLegacyMetadata::MUSHROOM_BLOCK_ALL_STEM));
|
||||
$this->map(Blocks::AMETHYST_CLUSTER(), fn(AmethystCluster $block) => Writer::create(
|
||||
match($stage = $block->getStage()){
|
||||
@ -1056,19 +1094,18 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
})
|
||||
->writeBlockFace($block->getFacing())
|
||||
);
|
||||
$this->map(Blocks::ANDESITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_ANDESITE));
|
||||
$this->mapSlab(Blocks::ANDESITE_SLAB(), Ids::ANDESITE_SLAB, Ids::ANDESITE_DOUBLE_SLAB);
|
||||
$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));
|
||||
$this->map(Blocks::ANVIL(), function(Anvil $block) : Writer{
|
||||
return Writer::create(Ids::ANVIL)
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeString(StateNames::DAMAGE, match($damage = $block->getDamage()){
|
||||
0 => StringValues::DAMAGE_UNDAMAGED,
|
||||
1 => StringValues::DAMAGE_SLIGHTLY_DAMAGED,
|
||||
2 => StringValues::DAMAGE_VERY_DAMAGED,
|
||||
default => throw new BlockStateSerializeException("Invalid Anvil damage {$damage}"),
|
||||
});
|
||||
});
|
||||
$this->map(Blocks::ANDESITE_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::ANDESITE_WALL)));
|
||||
$this->map(Blocks::ANVIL(), fn(Anvil $block) : Writer => Writer::create(
|
||||
match($damage = $block->getDamage()){
|
||||
0 => Ids::ANVIL,
|
||||
1 => Ids::CHIPPED_ANVIL,
|
||||
2 => Ids::DAMAGED_ANVIL,
|
||||
default => throw new BlockStateSerializeException("Invalid Anvil damage {$damage}"),
|
||||
})
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
);
|
||||
$this->map(Blocks::BAMBOO(), function(Bamboo $block) : Writer{
|
||||
return Writer::create(Ids::BAMBOO)
|
||||
->writeBool(StateNames::AGE_BIT, $block->isReady())
|
||||
@ -1136,7 +1173,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapStairs(Blocks::BLACKSTONE_STAIRS(), Ids::BLACKSTONE_STAIRS);
|
||||
$this->map(Blocks::BLACKSTONE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::BLACKSTONE_WALL)));
|
||||
$this->map(Blocks::BLAST_FURNACE(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::BLAST_FURNACE, Ids::LIT_BLAST_FURNACE));
|
||||
$this->map(Blocks::BLUE_TORCH(), fn(Torch $block) => Helper::encodeColoredTorch($block, false, Writer::create(Ids::COLORED_TORCH_BP)));
|
||||
$this->map(Blocks::BLUE_TORCH(), fn(Torch $block) => Helper::encodeTorch($block, Writer::create(Ids::COLORED_TORCH_BLUE)));
|
||||
$this->map(Blocks::BONE_BLOCK(), function(BoneBlock $block) : Writer{
|
||||
return Writer::create(Ids::BONE_BLOCK)
|
||||
->writeInt(StateNames::DEPRECATED, 0)
|
||||
@ -1148,9 +1185,9 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeBool(StateNames::BREWING_STAND_SLOT_B_BIT, $block->hasSlot(BrewingStandSlot::SOUTHWEST))
|
||||
->writeBool(StateNames::BREWING_STAND_SLOT_C_BIT, $block->hasSlot(BrewingStandSlot::NORTHWEST));
|
||||
});
|
||||
$this->map(Blocks::BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::BRICK_SLAB, StringValues::STONE_SLAB_TYPE_BRICK));
|
||||
$this->mapSlab(Blocks::BRICK_SLAB(), Ids::BRICK_SLAB, Ids::BRICK_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::BRICK_STAIRS(), Ids::BRICK_STAIRS);
|
||||
$this->map(Blocks::BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_BRICK));
|
||||
$this->map(Blocks::BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::BRICK_WALL)));
|
||||
$this->map(Blocks::BROWN_MUSHROOM_BLOCK(), fn(BrownMushroomBlock $block) => Helper::encodeMushroomBlock($block, new Writer(Ids::BROWN_MUSHROOM_BLOCK)));
|
||||
$this->map(Blocks::CACTUS(), function(Cactus $block) : Writer{
|
||||
return Writer::create(Ids::CACTUS)
|
||||
@ -1160,6 +1197,11 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
return Writer::create(Ids::CAKE)
|
||||
->writeInt(StateNames::BITE_COUNTER, $block->getBites());
|
||||
});
|
||||
$this->map(Blocks::CAMPFIRE(), function(Campfire $block) : Writer{
|
||||
return Writer::create(Ids::CAMPFIRE)
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeBool(StateNames::EXTINGUISHED, !$block->isLit());
|
||||
});
|
||||
$this->map(Blocks::CARROTS(), fn(Carrot $block) => Helper::encodeCrops($block, new Writer(Ids::CARROTS)));
|
||||
$this->map(Blocks::CARVED_PUMPKIN(), function(CarvedPumpkin $block) : Writer{
|
||||
return Writer::create(Ids::CARVED_PUMPKIN)
|
||||
@ -1193,10 +1235,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeLegacyHorizontalFacing($block->getFacing())
|
||||
->writeInt(StateNames::BOOKS_STORED, $flags);
|
||||
});
|
||||
$this->map(Blocks::CHISELED_QUARTZ(), fn(SimplePillar $block) => Helper::encodeQuartz(StringValues::CHISEL_TYPE_CHISELED, $block->getAxis()));
|
||||
$this->map(Blocks::CHISELED_RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_HEIROGLYPHS));
|
||||
$this->map(Blocks::CHISELED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_HEIROGLYPHS));
|
||||
$this->map(Blocks::CHISELED_STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_CHISELED));
|
||||
$this->map(Blocks::CHISELED_QUARTZ(), fn(SimplePillar $block) => Helper::encodeQuartz($block->getAxis(), Writer::create(Ids::CHISELED_QUARTZ_BLOCK)));
|
||||
$this->map(Blocks::CHORUS_FLOWER(), function(ChorusFlower $block) : Writer{
|
||||
return Writer::create(Ids::CHORUS_FLOWER)
|
||||
->writeInt(StateNames::AGE, $block->getAge());
|
||||
@ -1204,9 +1243,9 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->mapSlab(Blocks::COBBLED_DEEPSLATE_SLAB(), Ids::COBBLED_DEEPSLATE_SLAB, Ids::COBBLED_DEEPSLATE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::COBBLED_DEEPSLATE_STAIRS(), Ids::COBBLED_DEEPSLATE_STAIRS);
|
||||
$this->map(Blocks::COBBLED_DEEPSLATE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::COBBLED_DEEPSLATE_WALL)));
|
||||
$this->map(Blocks::COBBLESTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::COBBLESTONE_SLAB, StringValues::STONE_SLAB_TYPE_COBBLESTONE));
|
||||
$this->mapSlab(Blocks::COBBLESTONE_SLAB(), Ids::COBBLESTONE_SLAB, Ids::COBBLESTONE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::COBBLESTONE_STAIRS(), Ids::STONE_STAIRS);
|
||||
$this->map(Blocks::COBBLESTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_COBBLESTONE));
|
||||
$this->map(Blocks::COBBLESTONE_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::COBBLESTONE_WALL)));
|
||||
$this->map(Blocks::COPPER(), function(Copper $block) : Writer{
|
||||
$oxidation = $block->getOxidation();
|
||||
return new Writer($block->isWaxed() ?
|
||||
@ -1214,6 +1253,40 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
Helper::selectCopperId($oxidation, Ids::COPPER_BLOCK, Ids::EXPOSED_COPPER, Ids::WEATHERED_COPPER, Ids::OXIDIZED_COPPER)
|
||||
);
|
||||
});
|
||||
$this->map(Blocks::CHISELED_COPPER(), function(Copper $block) : Writer{
|
||||
$oxidation = $block->getOxidation();
|
||||
return new Writer($block->isWaxed() ?
|
||||
Helper::selectCopperId($oxidation,
|
||||
Ids::WAXED_CHISELED_COPPER,
|
||||
Ids::WAXED_EXPOSED_CHISELED_COPPER,
|
||||
Ids::WAXED_WEATHERED_CHISELED_COPPER,
|
||||
Ids::WAXED_OXIDIZED_CHISELED_COPPER
|
||||
) :
|
||||
Helper::selectCopperId($oxidation,
|
||||
Ids::CHISELED_COPPER,
|
||||
Ids::EXPOSED_CHISELED_COPPER,
|
||||
Ids::WEATHERED_CHISELED_COPPER,
|
||||
Ids::OXIDIZED_CHISELED_COPPER
|
||||
)
|
||||
);
|
||||
});
|
||||
$this->map(Blocks::COPPER_GRATE(), function(CopperGrate $block) : Writer{
|
||||
$oxidation = $block->getOxidation();
|
||||
return new Writer($block->isWaxed() ?
|
||||
Helper::selectCopperId($oxidation,
|
||||
Ids::WAXED_COPPER_GRATE,
|
||||
Ids::WAXED_EXPOSED_COPPER_GRATE,
|
||||
Ids::WAXED_WEATHERED_COPPER_GRATE,
|
||||
Ids::WAXED_OXIDIZED_COPPER_GRATE
|
||||
) :
|
||||
Helper::selectCopperId($oxidation,
|
||||
Ids::COPPER_GRATE,
|
||||
Ids::EXPOSED_COPPER_GRATE,
|
||||
Ids::WEATHERED_COPPER_GRATE,
|
||||
Ids::OXIDIZED_COPPER_GRATE
|
||||
)
|
||||
);
|
||||
});
|
||||
$this->map(Blocks::CUT_COPPER(), function(Copper $block) : Writer{
|
||||
$oxidation = $block->getOxidation();
|
||||
return new Writer($block->isWaxed() ?
|
||||
@ -1281,20 +1354,76 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
)
|
||||
);
|
||||
});
|
||||
$this->map(Blocks::COPPER_BULB(), function(CopperBulb $block) : Writer{
|
||||
$oxidation = $block->getOxidation();
|
||||
return Writer::create($block->isWaxed() ?
|
||||
Helper::selectCopperId($oxidation,
|
||||
Ids::WAXED_COPPER_BULB,
|
||||
Ids::WAXED_EXPOSED_COPPER_BULB,
|
||||
Ids::WAXED_WEATHERED_COPPER_BULB,
|
||||
Ids::WAXED_OXIDIZED_COPPER_BULB) :
|
||||
Helper::selectCopperId($oxidation,
|
||||
Ids::COPPER_BULB,
|
||||
Ids::EXPOSED_COPPER_BULB,
|
||||
Ids::WEATHERED_COPPER_BULB,
|
||||
Ids::OXIDIZED_COPPER_BULB
|
||||
))
|
||||
->writeBool(StateNames::LIT, $block->isLit())
|
||||
->writeBool(StateNames::POWERED_BIT, $block->isPowered());
|
||||
});
|
||||
$this->map(Blocks::COPPER_DOOR(), function(CopperDoor $block) : Writer{
|
||||
$oxidation = $block->getOxidation();
|
||||
return Helper::encodeDoor(
|
||||
$block,
|
||||
new Writer($block->isWaxed() ?
|
||||
Helper::selectCopperId(
|
||||
$oxidation,
|
||||
Ids::WAXED_COPPER_DOOR,
|
||||
Ids::WAXED_EXPOSED_COPPER_DOOR,
|
||||
Ids::WAXED_WEATHERED_COPPER_DOOR,
|
||||
Ids::WAXED_OXIDIZED_COPPER_DOOR
|
||||
) :
|
||||
Helper::selectCopperId(
|
||||
$oxidation,
|
||||
Ids::COPPER_DOOR,
|
||||
Ids::EXPOSED_COPPER_DOOR,
|
||||
Ids::WEATHERED_COPPER_DOOR,
|
||||
Ids::OXIDIZED_COPPER_DOOR
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
$this->map(Blocks::COPPER_TRAPDOOR(), function(CopperTrapdoor $block) : Writer{
|
||||
$oxidation = $block->getOxidation();
|
||||
return Helper::encodeTrapdoor(
|
||||
$block,
|
||||
new Writer($block->isWaxed() ?
|
||||
Helper::selectCopperId(
|
||||
$oxidation,
|
||||
Ids::WAXED_COPPER_TRAPDOOR,
|
||||
Ids::WAXED_EXPOSED_COPPER_TRAPDOOR,
|
||||
Ids::WAXED_WEATHERED_COPPER_TRAPDOOR,
|
||||
Ids::WAXED_OXIDIZED_COPPER_TRAPDOOR
|
||||
) :
|
||||
Helper::selectCopperId(
|
||||
$oxidation,
|
||||
Ids::COPPER_TRAPDOOR,
|
||||
Ids::EXPOSED_COPPER_TRAPDOOR,
|
||||
Ids::WEATHERED_COPPER_TRAPDOOR,
|
||||
Ids::OXIDIZED_COPPER_TRAPDOOR
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
$this->map(Blocks::COCOA_POD(), function(CocoaBlock $block) : Writer{
|
||||
return Writer::create(Ids::COCOA)
|
||||
->writeInt(StateNames::AGE, $block->getAge())
|
||||
->writeLegacyHorizontalFacing(Facing::opposite($block->getFacing()));
|
||||
});
|
||||
$this->map(Blocks::COMPOUND_CREATOR(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_COMPOUND_CREATOR, new Writer(Ids::CHEMISTRY_TABLE)));
|
||||
$this->map(Blocks::CRACKED_STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_CRACKED));
|
||||
$this->map(Blocks::CUT_RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_CUT));
|
||||
$this->map(Blocks::CUT_RED_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_CUT_RED_SANDSTONE));
|
||||
$this->map(Blocks::CUT_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_CUT));
|
||||
$this->map(Blocks::CUT_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_CUT_SANDSTONE));
|
||||
$this->map(Blocks::DARK_PRISMARINE(), fn() => Writer::create(Ids::PRISMARINE)
|
||||
->writeString(StateNames::PRISMARINE_BLOCK_TYPE, StringValues::PRISMARINE_BLOCK_TYPE_DARK));
|
||||
$this->map(Blocks::DARK_PRISMARINE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_PRISMARINE_DARK));
|
||||
$this->map(Blocks::COMPOUND_CREATOR(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, Writer::create(Ids::COMPOUND_CREATOR)));
|
||||
$this->mapSlab(Blocks::CUT_RED_SANDSTONE_SLAB(), Ids::CUT_RED_SANDSTONE_SLAB, Ids::CUT_RED_SANDSTONE_DOUBLE_SLAB);
|
||||
$this->mapSlab(Blocks::CUT_SANDSTONE_SLAB(), Ids::CUT_SANDSTONE_SLAB, Ids::CUT_SANDSTONE_DOUBLE_SLAB);
|
||||
$this->mapSlab(Blocks::DARK_PRISMARINE_SLAB(), Ids::DARK_PRISMARINE_SLAB, Ids::DARK_PRISMARINE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::DARK_PRISMARINE_STAIRS(), Ids::DARK_PRISMARINE_STAIRS);
|
||||
$this->map(Blocks::DAYLIGHT_SENSOR(), function(DaylightSensor $block) : Writer{
|
||||
return Writer::create($block->isInverted() ? Ids::DAYLIGHT_DETECTOR_INVERTED : Ids::DAYLIGHT_DETECTOR)
|
||||
@ -1316,23 +1445,18 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeBool(StateNames::RAIL_DATA_BIT, $block->isActivated())
|
||||
->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
|
||||
});
|
||||
$this->map(Blocks::DIORITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_DIORITE));
|
||||
$this->mapSlab(Blocks::DIORITE_SLAB(), Ids::DIORITE_SLAB, Ids::DIORITE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::DIORITE_STAIRS(), Ids::DIORITE_STAIRS);
|
||||
$this->map(Blocks::DIORITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_DIORITE));
|
||||
$this->map(Blocks::DIORITE_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::DIORITE_WALL)));
|
||||
$this->map(Blocks::DIRT(), function(Dirt $block) : Writer{
|
||||
$dirtType = $block->getDirtType();
|
||||
if($dirtType === DirtType::ROOTED){
|
||||
return new Writer(Ids::DIRT_WITH_ROOTS);
|
||||
}
|
||||
return Writer::create(Ids::DIRT)
|
||||
->writeString(StateNames::DIRT_TYPE, match($dirtType){
|
||||
DirtType::COARSE => StringValues::DIRT_TYPE_COARSE,
|
||||
DirtType::NORMAL => StringValues::DIRT_TYPE_NORMAL,
|
||||
//ROOTED was already checked above
|
||||
});
|
||||
return Writer::create(match($block->getDirtType()){
|
||||
DirtType::NORMAL => Ids::DIRT,
|
||||
DirtType::COARSE => Ids::COARSE_DIRT,
|
||||
DirtType::ROOTED => Ids::DIRT_WITH_ROOTS,
|
||||
});
|
||||
});
|
||||
$this->map(Blocks::DOUBLE_TALLGRASS(), fn(DoubleTallGrass $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::TALL_GRASS)));
|
||||
$this->map(Blocks::ELEMENT_CONSTRUCTOR(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_ELEMENT_CONSTRUCTOR, new Writer(Ids::CHEMISTRY_TABLE)));
|
||||
$this->map(Blocks::ELEMENT_CONSTRUCTOR(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, Writer::create(Ids::ELEMENT_CONSTRUCTOR)));
|
||||
$this->map(Blocks::ENDER_CHEST(), function(EnderChest $block) : Writer{
|
||||
return Writer::create(Ids::ENDER_CHEST)
|
||||
->writeCardinalHorizontalFacing($block->getFacing());
|
||||
@ -1346,10 +1470,10 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
return Writer::create(Ids::END_ROD)
|
||||
->writeEndRodFacingDirection($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::END_STONE_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_END_STONE_BRICK));
|
||||
$this->mapSlab(Blocks::END_STONE_BRICK_SLAB(), Ids::END_STONE_BRICK_SLAB, Ids::END_STONE_BRICK_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::END_STONE_BRICK_STAIRS(), Ids::END_BRICK_STAIRS);
|
||||
$this->map(Blocks::END_STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_END_BRICK));
|
||||
$this->map(Blocks::FAKE_WOODEN_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::PETRIFIED_OAK_SLAB, StringValues::STONE_SLAB_TYPE_WOOD));
|
||||
$this->map(Blocks::END_STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::END_STONE_BRICK_WALL)));
|
||||
$this->mapSlab(Blocks::FAKE_WOODEN_SLAB(), Ids::PETRIFIED_OAK_SLAB, Ids::PETRIFIED_OAK_DOUBLE_SLAB);
|
||||
$this->map(Blocks::FARMLAND(), function(Farmland $block) : Writer{
|
||||
return Writer::create(Ids::FARMLAND)
|
||||
->writeInt(StateNames::MOISTURIZED_AMOUNT, $block->getWetness());
|
||||
@ -1380,10 +1504,10 @@ 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_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_GRANITE));
|
||||
$this->mapSlab(Blocks::GRANITE_SLAB(), Ids::GRANITE_SLAB, Ids::GRANITE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::GRANITE_STAIRS(), Ids::GRANITE_STAIRS);
|
||||
$this->map(Blocks::GRANITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_GRANITE));
|
||||
$this->map(Blocks::GREEN_TORCH(), fn(Torch $block) => Helper::encodeColoredTorch($block, true, Writer::create(Ids::COLORED_TORCH_RG)));
|
||||
$this->map(Blocks::GRANITE_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::GRANITE_WALL)));
|
||||
$this->map(Blocks::GREEN_TORCH(), fn(Torch $block) => Helper::encodeTorch($block, Writer::create(Ids::COLORED_TORCH_GREEN)));
|
||||
$this->map(Blocks::HAY_BALE(), function(HayBale $block) : Writer{
|
||||
return Writer::create(Ids::HAY_BLOCK)
|
||||
->writeInt(StateNames::DEPRECATED, 0)
|
||||
@ -1394,22 +1518,10 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeBool(StateNames::TOGGLE_BIT, $block->isPowered())
|
||||
->writeFacingWithoutUp($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::INFESTED_CHISELED_STONE_BRICK(), fn() => Writer::create(Ids::MONSTER_EGG)
|
||||
->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_CHISELED_STONE_BRICK));
|
||||
$this->map(Blocks::INFESTED_COBBLESTONE(), fn() => Writer::create(Ids::MONSTER_EGG)
|
||||
->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_COBBLESTONE));
|
||||
$this->map(Blocks::INFESTED_CRACKED_STONE_BRICK(), fn() => Writer::create(Ids::MONSTER_EGG)
|
||||
->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_CRACKED_STONE_BRICK));
|
||||
$this->map(Blocks::INFESTED_MOSSY_STONE_BRICK(), fn() => Writer::create(Ids::MONSTER_EGG)
|
||||
->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_MOSSY_STONE_BRICK));
|
||||
$this->map(Blocks::INFESTED_STONE(), fn() => Writer::create(Ids::MONSTER_EGG)
|
||||
->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_STONE));
|
||||
$this->map(Blocks::INFESTED_STONE_BRICK(), fn() => Writer::create(Ids::MONSTER_EGG)
|
||||
->writeString(StateNames::MONSTER_EGG_STONE_TYPE, StringValues::MONSTER_EGG_STONE_TYPE_STONE_BRICK));
|
||||
$this->map(Blocks::IRON_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::IRON_DOOR)));
|
||||
$this->map(Blocks::IRON_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::IRON_TRAPDOOR)));
|
||||
$this->map(Blocks::ITEM_FRAME(), fn(ItemFrame $block) => Helper::encodeItemFrame($block, Ids::FRAME));
|
||||
$this->map(Blocks::LAB_TABLE(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_LAB_TABLE, new Writer(Ids::CHEMISTRY_TABLE)));
|
||||
$this->map(Blocks::LAB_TABLE(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, Writer::create(Ids::LAB_TABLE)));
|
||||
$this->map(Blocks::LADDER(), function(Ladder $block) : Writer{
|
||||
return Writer::create(Ids::LADDER)
|
||||
->writeHorizontalFacing($block->getFacing());
|
||||
@ -1440,8 +1552,25 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
});
|
||||
});
|
||||
$this->map(Blocks::LIGHT(), function(Light $block) : Writer{
|
||||
return Writer::create(Ids::LIGHT_BLOCK)
|
||||
->writeInt(StateNames::BLOCK_LIGHT_LEVEL, $block->getLightLevel());
|
||||
return Writer::create(match($block->getLightLevel()){
|
||||
0 => Ids::LIGHT_BLOCK_0,
|
||||
1 => Ids::LIGHT_BLOCK_1,
|
||||
2 => Ids::LIGHT_BLOCK_2,
|
||||
3 => Ids::LIGHT_BLOCK_3,
|
||||
4 => Ids::LIGHT_BLOCK_4,
|
||||
5 => Ids::LIGHT_BLOCK_5,
|
||||
6 => Ids::LIGHT_BLOCK_6,
|
||||
7 => Ids::LIGHT_BLOCK_7,
|
||||
8 => Ids::LIGHT_BLOCK_8,
|
||||
9 => Ids::LIGHT_BLOCK_9,
|
||||
10 => Ids::LIGHT_BLOCK_10,
|
||||
11 => Ids::LIGHT_BLOCK_11,
|
||||
12 => Ids::LIGHT_BLOCK_12,
|
||||
13 => Ids::LIGHT_BLOCK_13,
|
||||
14 => Ids::LIGHT_BLOCK_14,
|
||||
15 => Ids::LIGHT_BLOCK_15,
|
||||
default => throw new BlockStateSerializeException("Invalid light level " . $block->getLightLevel()),
|
||||
});
|
||||
});
|
||||
$this->map(Blocks::LIGHTNING_ROD(), function(LightningRod $block) : Writer{
|
||||
return Writer::create(Ids::LIGHTNING_ROD)
|
||||
@ -1456,29 +1585,24 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
return Writer::create(Ids::LOOM)
|
||||
->writeLegacyHorizontalFacing($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::MATERIAL_REDUCER(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_MATERIAL_REDUCER, new Writer(Ids::CHEMISTRY_TABLE)));
|
||||
$this->map(Blocks::MATERIAL_REDUCER(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, Writer::create(Ids::MATERIAL_REDUCER)));
|
||||
$this->map(Blocks::MELON_STEM(), fn(MelonStem $block) => Helper::encodeStem($block, new Writer(Ids::MELON_STEM)));
|
||||
$this->map(Blocks::MOB_HEAD(), function(MobHead $block) : Writer{
|
||||
return Writer::create(Ids::SKULL)
|
||||
->writeFacingWithoutDown($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::MOSSY_COBBLESTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_MOSSY_COBBLESTONE));
|
||||
$this->mapSlab(Blocks::MOSSY_COBBLESTONE_SLAB(), Ids::MOSSY_COBBLESTONE_SLAB, Ids::MOSSY_COBBLESTONE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::MOSSY_COBBLESTONE_STAIRS(), Ids::MOSSY_COBBLESTONE_STAIRS);
|
||||
$this->map(Blocks::MOSSY_COBBLESTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_MOSSY_COBBLESTONE));
|
||||
$this->map(Blocks::MOSSY_STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_MOSSY));
|
||||
$this->map(Blocks::MOSSY_STONE_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_MOSSY_STONE_BRICK));
|
||||
$this->map(Blocks::MOSSY_COBBLESTONE_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::MOSSY_COBBLESTONE_WALL)));
|
||||
$this->mapSlab(Blocks::MOSSY_STONE_BRICK_SLAB(), Ids::MOSSY_STONE_BRICK_SLAB, Ids::MOSSY_STONE_BRICK_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::MOSSY_STONE_BRICK_STAIRS(), Ids::MOSSY_STONE_BRICK_STAIRS);
|
||||
$this->map(Blocks::MOSSY_STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_MOSSY_STONE_BRICK));
|
||||
$this->map(Blocks::MOSSY_STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::MOSSY_STONE_BRICK_WALL)));
|
||||
$this->mapSlab(Blocks::MUD_BRICK_SLAB(), Ids::MUD_BRICK_SLAB, Ids::MUD_BRICK_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::MUD_BRICK_STAIRS(), Ids::MUD_BRICK_STAIRS);
|
||||
$this->map(Blocks::MUD_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::MUD_BRICK_WALL)));
|
||||
$this->map(Blocks::MUDDY_MANGROVE_ROOTS(), fn(SimplePillar $block) => Writer::create(Ids::MUDDY_MANGROVE_ROOTS)
|
||||
->writePillarAxis($block->getAxis()));
|
||||
$this->map(Blocks::MUSHROOM_STEM(), fn() => Writer::create(Ids::BROWN_MUSHROOM_BLOCK)
|
||||
$this->map(Blocks::MUSHROOM_STEM(), fn() => Writer::create(Ids::MUSHROOM_STEM)
|
||||
->writeInt(StateNames::HUGE_MUSHROOM_BITS, BlockLegacyMetadata::MUSHROOM_BLOCK_STEM));
|
||||
$this->map(Blocks::NETHER_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::NETHER_BRICK_SLAB, StringValues::STONE_SLAB_TYPE_NETHER_BRICK));
|
||||
$this->mapSlab(Blocks::NETHER_BRICK_SLAB(), Ids::NETHER_BRICK_SLAB, Ids::NETHER_BRICK_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::NETHER_BRICK_STAIRS(), Ids::NETHER_BRICK_STAIRS);
|
||||
$this->map(Blocks::NETHER_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_NETHER_BRICK));
|
||||
$this->map(Blocks::NETHER_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::NETHER_BRICK_WALL)));
|
||||
$this->map(Blocks::NETHER_PORTAL(), function(NetherPortal $block) : Writer{
|
||||
return Writer::create(Ids::PORTAL)
|
||||
->writeString(StateNames::PORTAL_AXIS, match($block->getAxis()){
|
||||
@ -1511,7 +1635,7 @@ 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_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_ANDESITE));
|
||||
$this->mapSlab(Blocks::POLISHED_ANDESITE_SLAB(), Ids::POLISHED_ANDESITE_SLAB, Ids::POLISHED_ANDESITE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::POLISHED_ANDESITE_STAIRS(), Ids::POLISHED_ANDESITE_STAIRS);
|
||||
$this->map(Blocks::POLISHED_BASALT(), function(SimplePillar $block) : Writer{
|
||||
return Writer::create(Ids::POLISHED_BASALT)
|
||||
@ -1528,46 +1652,40 @@ 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_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_DIORITE));
|
||||
$this->mapSlab(Blocks::POLISHED_DIORITE_SLAB(), Ids::POLISHED_DIORITE_SLAB, Ids::POLISHED_DIORITE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::POLISHED_DIORITE_STAIRS(), Ids::POLISHED_DIORITE_STAIRS);
|
||||
$this->map(Blocks::POLISHED_GRANITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_GRANITE));
|
||||
$this->mapSlab(Blocks::POLISHED_GRANITE_SLAB(), Ids::POLISHED_GRANITE_SLAB, Ids::POLISHED_GRANITE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::POLISHED_GRANITE_STAIRS(), Ids::POLISHED_GRANITE_STAIRS);
|
||||
$this->mapSlab(Blocks::POLISHED_TUFF_SLAB(), Ids::POLISHED_TUFF_SLAB, Ids::POLISHED_TUFF_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::POLISHED_TUFF_STAIRS(), Ids::POLISHED_TUFF_STAIRS);
|
||||
$this->map(Blocks::POLISHED_TUFF_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::POLISHED_TUFF_WALL)));
|
||||
$this->map(Blocks::POTATOES(), fn(Potato $block) => Helper::encodeCrops($block, new Writer(Ids::POTATOES)));
|
||||
$this->map(Blocks::POWERED_RAIL(), function(PoweredRail $block) : Writer{
|
||||
return Writer::create(Ids::GOLDEN_RAIL)
|
||||
->writeBool(StateNames::RAIL_DATA_BIT, $block->isPowered())
|
||||
->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
|
||||
});
|
||||
$this->map(Blocks::PRISMARINE(), fn() => Writer::create(Ids::PRISMARINE)
|
||||
->writeString(StateNames::PRISMARINE_BLOCK_TYPE, StringValues::PRISMARINE_BLOCK_TYPE_DEFAULT));
|
||||
$this->map(Blocks::PRISMARINE_BRICKS(), fn() => Writer::create(Ids::PRISMARINE)
|
||||
->writeString(StateNames::PRISMARINE_BLOCK_TYPE, StringValues::PRISMARINE_BLOCK_TYPE_BRICKS));
|
||||
$this->map(Blocks::PRISMARINE_BRICKS_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_PRISMARINE_BRICK));
|
||||
$this->mapSlab(Blocks::PRISMARINE_BRICKS_SLAB(), Ids::PRISMARINE_BRICK_SLAB, Ids::PRISMARINE_BRICK_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::PRISMARINE_BRICKS_STAIRS(), Ids::PRISMARINE_BRICKS_STAIRS);
|
||||
$this->map(Blocks::PRISMARINE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_PRISMARINE_ROUGH));
|
||||
$this->mapSlab(Blocks::PRISMARINE_SLAB(), Ids::PRISMARINE_SLAB, Ids::PRISMARINE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::PRISMARINE_STAIRS(), Ids::PRISMARINE_STAIRS);
|
||||
$this->map(Blocks::PRISMARINE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_PRISMARINE));
|
||||
$this->map(Blocks::PRISMARINE_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::PRISMARINE_WALL)));
|
||||
$this->map(Blocks::PUMPKIN(), function() : Writer{
|
||||
return Writer::create(Ids::PUMPKIN)
|
||||
->writeCardinalHorizontalFacing(Facing::SOUTH); //no longer used
|
||||
});
|
||||
$this->map(Blocks::PUMPKIN_STEM(), fn(PumpkinStem $block) => Helper::encodeStem($block, new Writer(Ids::PUMPKIN_STEM)));
|
||||
$this->map(Blocks::PURPLE_TORCH(), fn(Torch $block) => Helper::encodeColoredTorch($block, true, Writer::create(Ids::COLORED_TORCH_BP)));
|
||||
$this->map(Blocks::PURPUR(), function() : Writer{
|
||||
return Writer::create(Ids::PURPUR_BLOCK)
|
||||
->writeString(StateNames::CHISEL_TYPE, StringValues::CHISEL_TYPE_DEFAULT)
|
||||
->writePillarAxis(Axis::Y); //useless, but MCPE wants it
|
||||
});
|
||||
$this->map(Blocks::PURPUR(), fn() => Writer::create(Ids::PURPUR_BLOCK)->writePillarAxis(Axis::Y));
|
||||
$this->map(Blocks::PURPLE_TORCH(), fn(Torch $block) => Helper::encodeTorch($block, Writer::create(Ids::COLORED_TORCH_PURPLE)));
|
||||
$this->map(Blocks::PURPUR_PILLAR(), function(SimplePillar $block) : Writer{
|
||||
return Writer::create(Ids::PURPUR_BLOCK)
|
||||
->writeString(StateNames::CHISEL_TYPE, StringValues::CHISEL_TYPE_LINES)
|
||||
return Writer::create(Ids::PURPUR_PILLAR)
|
||||
->writePillarAxis($block->getAxis());
|
||||
});
|
||||
$this->map(Blocks::PURPUR_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_PURPUR));
|
||||
$this->mapSlab(Blocks::PURPUR_SLAB(), Ids::PURPUR_SLAB, Ids::PURPUR_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::PURPUR_STAIRS(), Ids::PURPUR_STAIRS);
|
||||
$this->map(Blocks::QUARTZ(), fn() => Helper::encodeQuartz(StringValues::CHISEL_TYPE_DEFAULT, Axis::Y));
|
||||
$this->map(Blocks::QUARTZ_PILLAR(), fn(SimplePillar $block) => Helper::encodeQuartz(StringValues::CHISEL_TYPE_LINES, $block->getAxis()));
|
||||
$this->map(Blocks::QUARTZ_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::QUARTZ_SLAB, StringValues::STONE_SLAB_TYPE_QUARTZ));
|
||||
$this->map(Blocks::QUARTZ(), fn() => Helper::encodeQuartz(Axis::Y, Writer::create(Ids::QUARTZ_BLOCK)));
|
||||
$this->map(Blocks::QUARTZ_PILLAR(), fn(SimplePillar $block) => Helper::encodeQuartz($block->getAxis(), Writer::create(Ids::QUARTZ_PILLAR)));
|
||||
$this->mapSlab(Blocks::QUARTZ_SLAB(), Ids::QUARTZ_SLAB, Ids::QUARTZ_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::QUARTZ_STAIRS(), Ids::QUARTZ_STAIRS);
|
||||
$this->map(Blocks::RAIL(), function(Rail $block) : Writer{
|
||||
return Writer::create(Ids::RAIL)
|
||||
@ -1595,23 +1713,17 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeInt(StateNames::REDSTONE_SIGNAL, $block->getOutputSignalStrength());
|
||||
});
|
||||
$this->map(Blocks::RED_MUSHROOM_BLOCK(), fn(RedMushroomBlock $block) => Helper::encodeMushroomBlock($block, new Writer(Ids::RED_MUSHROOM_BLOCK)));
|
||||
$this->map(Blocks::RED_NETHER_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_RED_NETHER_BRICK));
|
||||
$this->mapSlab(Blocks::RED_NETHER_BRICK_SLAB(), Ids::RED_NETHER_BRICK_SLAB, Ids::RED_NETHER_BRICK_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::RED_NETHER_BRICK_STAIRS(), Ids::RED_NETHER_BRICK_STAIRS);
|
||||
$this->map(Blocks::RED_NETHER_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_RED_NETHER_BRICK));
|
||||
$this->map(Blocks::RED_SAND(), fn() => Writer::create(Ids::SAND)
|
||||
->writeString(StateNames::SAND_TYPE, StringValues::SAND_TYPE_RED));
|
||||
$this->map(Blocks::RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_DEFAULT));
|
||||
$this->map(Blocks::RED_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_RED_SANDSTONE));
|
||||
$this->map(Blocks::RED_NETHER_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::RED_NETHER_BRICK_WALL)));
|
||||
$this->mapSlab(Blocks::RED_SANDSTONE_SLAB(), Ids::RED_SANDSTONE_SLAB, Ids::RED_SANDSTONE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::RED_SANDSTONE_STAIRS(), Ids::RED_SANDSTONE_STAIRS);
|
||||
$this->map(Blocks::RED_SANDSTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_RED_SANDSTONE));
|
||||
$this->map(Blocks::RED_TORCH(), fn(Torch $block) => Helper::encodeColoredTorch($block, false, Writer::create(Ids::COLORED_TORCH_RG)));
|
||||
$this->map(Blocks::RED_SANDSTONE_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::RED_SANDSTONE_WALL)));
|
||||
$this->map(Blocks::RED_TORCH(), fn(Torch $block) => Helper::encodeTorch($block, Writer::create(Ids::COLORED_TORCH_RED)));
|
||||
$this->map(Blocks::ROSE_BUSH(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::ROSE_BUSH)));
|
||||
$this->map(Blocks::SAND(), fn() => Writer::create(Ids::SAND)
|
||||
->writeString(StateNames::SAND_TYPE, StringValues::SAND_TYPE_NORMAL));
|
||||
$this->map(Blocks::SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_DEFAULT));
|
||||
$this->map(Blocks::SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::SANDSTONE_SLAB, StringValues::STONE_SLAB_TYPE_SANDSTONE));
|
||||
$this->mapSlab(Blocks::SANDSTONE_SLAB(), Ids::SANDSTONE_SLAB, Ids::SANDSTONE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::SANDSTONE_STAIRS(), Ids::SANDSTONE_STAIRS);
|
||||
$this->map(Blocks::SANDSTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_SANDSTONE));
|
||||
$this->map(Blocks::SANDSTONE_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::SANDSTONE_WALL)));
|
||||
$this->map(Blocks::SEA_PICKLE(), function(SeaPickle $block) : Writer{
|
||||
return Writer::create(Ids::SEA_PICKLE)
|
||||
->writeBool(StateNames::DEAD_BIT, !$block->isUnderwater())
|
||||
@ -1623,21 +1735,24 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop());
|
||||
});
|
||||
$this->map(Blocks::SMOKER(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::SMOKER, Ids::LIT_SMOKER));
|
||||
$this->map(Blocks::SMOOTH_QUARTZ(), fn() => Helper::encodeQuartz(StringValues::CHISEL_TYPE_SMOOTH, Axis::Y));
|
||||
$this->map(Blocks::SMOOTH_QUARTZ_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_SMOOTH_QUARTZ));
|
||||
$this->map(Blocks::SMOOTH_QUARTZ(), fn() => Helper::encodeQuartz(Axis::Y, Writer::create(Ids::SMOOTH_QUARTZ)));
|
||||
$this->mapSlab(Blocks::SMOOTH_QUARTZ_SLAB(), Ids::SMOOTH_QUARTZ_SLAB, Ids::SMOOTH_QUARTZ_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::SMOOTH_QUARTZ_STAIRS(), Ids::SMOOTH_QUARTZ_STAIRS);
|
||||
$this->map(Blocks::SMOOTH_RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_SMOOTH));
|
||||
$this->map(Blocks::SMOOTH_RED_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_SMOOTH_RED_SANDSTONE));
|
||||
$this->mapSlab(Blocks::SMOOTH_RED_SANDSTONE_SLAB(), Ids::SMOOTH_RED_SANDSTONE_SLAB, Ids::SMOOTH_RED_SANDSTONE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::SMOOTH_RED_SANDSTONE_STAIRS(), Ids::SMOOTH_RED_SANDSTONE_STAIRS);
|
||||
$this->map(Blocks::SMOOTH_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_SMOOTH));
|
||||
$this->map(Blocks::SMOOTH_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_SMOOTH_SANDSTONE));
|
||||
$this->mapSlab(Blocks::SMOOTH_SANDSTONE_SLAB(), Ids::SMOOTH_SANDSTONE_SLAB, Ids::SMOOTH_SANDSTONE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::SMOOTH_SANDSTONE_STAIRS(), Ids::SMOOTH_SANDSTONE_STAIRS);
|
||||
$this->map(Blocks::SMOOTH_STONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::SMOOTH_STONE_SLAB, StringValues::STONE_SLAB_TYPE_SMOOTH_STONE));
|
||||
$this->mapSlab(Blocks::SMOOTH_STONE_SLAB(), Ids::SMOOTH_STONE_SLAB, Ids::SMOOTH_STONE_DOUBLE_SLAB);
|
||||
$this->map(Blocks::SNOW_LAYER(), function(SnowLayer $block) : Writer{
|
||||
return Writer::create(Ids::SNOW_LAYER)
|
||||
->writeBool(StateNames::COVERED_BIT, false)
|
||||
->writeInt(StateNames::HEIGHT, $block->getLayers() - 1);
|
||||
});
|
||||
$this->map(Blocks::SOUL_CAMPFIRE(), function(SoulCampfire $block) : Writer{
|
||||
return Writer::create(Ids::SOUL_CAMPFIRE)
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeBool(StateNames::EXTINGUISHED, !$block->isLit());
|
||||
});
|
||||
$this->map(Blocks::SOUL_FIRE(), function() : Writer{
|
||||
return Writer::create(Ids::SOUL_FIRE)
|
||||
->writeInt(StateNames::AGE, 0); //useless for soul fire, we don't track it
|
||||
@ -1650,19 +1765,15 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
return Writer::create(Ids::SOUL_TORCH)
|
||||
->writeTorchFacing($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::SPONGE(), function(Sponge $block) : Writer{
|
||||
return Writer::create(Ids::SPONGE)
|
||||
->writeString(StateNames::SPONGE_TYPE, $block->isWet() ? StringValues::SPONGE_TYPE_WET : StringValues::SPONGE_TYPE_DRY);
|
||||
});
|
||||
$this->map(Blocks::SPONGE(), fn(Sponge $block) => Writer::create($block->isWet() ? Ids::WET_SPONGE : Ids::SPONGE));
|
||||
$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));
|
||||
$this->map(Blocks::STONE_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::STONE_BRICK_SLAB, StringValues::STONE_SLAB_TYPE_STONE_BRICK));
|
||||
$this->mapSlab(Blocks::STONE_BRICK_SLAB(), Ids::STONE_BRICK_SLAB, Ids::STONE_BRICK_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::STONE_BRICK_STAIRS(), Ids::STONE_BRICK_STAIRS);
|
||||
$this->map(Blocks::STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_STONE_BRICK));
|
||||
$this->map(Blocks::STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::STONE_BRICK_WALL)));
|
||||
$this->map(Blocks::STONE_BUTTON(), fn(StoneButton $block) => Helper::encodeButton($block, new Writer(Ids::STONE_BUTTON)));
|
||||
$this->map(Blocks::STONE_PRESSURE_PLATE(), fn(StonePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::STONE_PRESSURE_PLATE)));
|
||||
$this->map(Blocks::STONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_STONE));
|
||||
$this->mapSlab(Blocks::STONE_SLAB(), Ids::NORMAL_STONE_SLAB, Ids::NORMAL_STONE_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::STONE_STAIRS(), Ids::NORMAL_STONE_STAIRS);
|
||||
$this->map(Blocks::SUGARCANE(), function(Sugarcane $block) : Writer{
|
||||
return Writer::create(Ids::REEDS)
|
||||
@ -1673,11 +1784,9 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
return Writer::create(Ids::SWEET_BERRY_BUSH)
|
||||
->writeInt(StateNames::GROWTH, $block->getAge());
|
||||
});
|
||||
$this->map(Blocks::TNT(), function(TNT $block) : Writer{
|
||||
return Writer::create(Ids::TNT)
|
||||
->writeBool(StateNames::ALLOW_UNDERWATER_BIT, $block->worksUnderwater())
|
||||
->writeBool(StateNames::EXPLODE_BIT, $block->isUnstable());
|
||||
});
|
||||
$this->map(Blocks::TNT(), fn(TNT $block) => Writer::create($block->worksUnderwater() ? Ids::UNDERWATER_TNT : Ids::TNT)
|
||||
->writeBool(StateNames::EXPLODE_BIT, $block->isUnstable())
|
||||
);
|
||||
$this->map(Blocks::TORCH(), function(Torch $block) : Writer{
|
||||
return Writer::create(Ids::TORCH)
|
||||
->writeTorchFacing($block->getFacing());
|
||||
@ -1703,6 +1812,12 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeBool(StateNames::POWERED_BIT, $block->isPowered())
|
||||
->writeLegacyHorizontalFacing($block->getFacing());
|
||||
});
|
||||
$this->mapSlab(Blocks::TUFF_BRICK_SLAB(), Ids::TUFF_BRICK_SLAB, Ids::TUFF_BRICK_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::TUFF_BRICK_STAIRS(), Ids::TUFF_BRICK_STAIRS);
|
||||
$this->map(Blocks::TUFF_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::TUFF_BRICK_WALL)));
|
||||
$this->mapSlab(Blocks::TUFF_SLAB(), Ids::TUFF_SLAB, Ids::TUFF_DOUBLE_SLAB);
|
||||
$this->mapStairs(Blocks::TUFF_STAIRS(), Ids::TUFF_STAIRS);
|
||||
$this->map(Blocks::TUFF_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::TUFF_WALL)));
|
||||
$this->map(Blocks::TWISTING_VINES(), function(NetherVines $block) : Writer{
|
||||
return Writer::create(Ids::TWISTING_VINES)
|
||||
->writeInt(StateNames::TWISTING_VINES_AGE, $block->getAge());
|
||||
@ -1719,17 +1834,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
return Writer::create(Ids::WALL_BANNER)
|
||||
->writeHorizontalFacing($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::WALL_CORAL_FAN(), function(WallCoralFan $block) : Writer{
|
||||
$coralType = $block->getCoralType();
|
||||
return Writer::create(match($coralType){
|
||||
CoralType::TUBE, CoralType::BRAIN => Ids::CORAL_FAN_HANG,
|
||||
CoralType::BUBBLE, CoralType::FIRE => Ids::CORAL_FAN_HANG2,
|
||||
CoralType::HORN => Ids::CORAL_FAN_HANG3,
|
||||
})
|
||||
->writeBool(StateNames::CORAL_HANG_TYPE_BIT, $coralType === CoralType::BRAIN || $coralType === CoralType::FIRE)
|
||||
->writeBool(StateNames::DEAD_BIT, $block->isDead())
|
||||
->writeCoralFacing($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::WATER(), fn(Water $block) => Helper::encodeLiquid($block, Ids::WATER, Ids::FLOWING_WATER));
|
||||
$this->map(Blocks::WEEPING_VINES(), function(NetherVines $block) : Writer{
|
||||
return Writer::create(Ids::WEEPING_VINES)
|
||||
|
@ -26,9 +26,6 @@ namespace pocketmine\data\bedrock\block\convert;
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\Button;
|
||||
use pocketmine\block\Candle;
|
||||
use pocketmine\block\Copper;
|
||||
use pocketmine\block\CopperSlab;
|
||||
use pocketmine\block\CopperStairs;
|
||||
use pocketmine\block\Crops;
|
||||
use pocketmine\block\DaylightSensor;
|
||||
use pocketmine\block\Door;
|
||||
@ -48,11 +45,10 @@ use pocketmine\block\Slab;
|
||||
use pocketmine\block\Stair;
|
||||
use pocketmine\block\Stem;
|
||||
use pocketmine\block\Trapdoor;
|
||||
use pocketmine\block\utils\CopperMaterial;
|
||||
use pocketmine\block\utils\CopperOxidation;
|
||||
use pocketmine\block\utils\SlabType;
|
||||
use pocketmine\block\VanillaBlocks;
|
||||
use pocketmine\block\Wall;
|
||||
use pocketmine\block\WallCoralFan;
|
||||
use pocketmine\block\WallSign;
|
||||
use pocketmine\block\WeightedPressurePlate;
|
||||
use pocketmine\block\Wood;
|
||||
@ -60,7 +56,6 @@ use pocketmine\data\bedrock\block\BlockLegacyMetadata;
|
||||
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
|
||||
use pocketmine\data\bedrock\block\BlockStateNames;
|
||||
use pocketmine\data\bedrock\block\BlockStateNames as StateNames;
|
||||
use pocketmine\data\bedrock\block\BlockStateStringValues as StringValues;
|
||||
use pocketmine\data\bedrock\MushroomBlockTypeIdMap;
|
||||
use pocketmine\math\Axis;
|
||||
use pocketmine\math\Facing;
|
||||
@ -102,24 +97,24 @@ final class BlockStateDeserializerHelper{
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-template TBlock of Copper|CopperSlab|CopperStairs
|
||||
* @phpstan-template TBlock of CopperMaterial
|
||||
*
|
||||
* @phpstan-param TBlock $block
|
||||
* @phpstan-return TBlock
|
||||
*/
|
||||
public static function decodeCopper(Copper|CopperSlab|CopperStairs $block, CopperOxidation $oxidation) : Copper|CopperSlab|CopperStairs{
|
||||
public static function decodeCopper(CopperMaterial $block, CopperOxidation $oxidation) : CopperMaterial{
|
||||
$block->setOxidation($oxidation);
|
||||
$block->setWaxed(false);
|
||||
return $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-template TBlock of Copper|CopperSlab|CopperStairs
|
||||
* @phpstan-template TBlock of CopperMaterial
|
||||
*
|
||||
* @phpstan-param TBlock $block
|
||||
* @phpstan-return TBlock
|
||||
*/
|
||||
public static function decodeWaxedCopper(Copper|CopperSlab|CopperStairs $block, CopperOxidation $oxidation) : Copper|CopperSlab|CopperStairs{
|
||||
public static function decodeWaxedCopper(CopperMaterial $block, CopperOxidation $oxidation) : CopperMaterial{
|
||||
$block->setOxidation($oxidation);
|
||||
$block->setWaxed(true);
|
||||
return $block;
|
||||
@ -212,8 +207,8 @@ final class BlockStateDeserializerHelper{
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function decodeMushroomBlock(RedMushroomBlock $block, BlockStateReader $in) : Block{
|
||||
switch($type = $in->readBoundedInt(BlockStateNames::HUGE_MUSHROOM_BITS, 0, 15)){
|
||||
case BlockLegacyMetadata::MUSHROOM_BLOCK_ALL_STEM: return VanillaBlocks::ALL_SIDED_MUSHROOM_STEM();
|
||||
case BlockLegacyMetadata::MUSHROOM_BLOCK_STEM: return VanillaBlocks::MUSHROOM_STEM();
|
||||
case BlockLegacyMetadata::MUSHROOM_BLOCK_ALL_STEM:
|
||||
case BlockLegacyMetadata::MUSHROOM_BLOCK_STEM: throw new BlockStateDeserializeException("This state does not exist");
|
||||
default:
|
||||
//invalid types get left as default
|
||||
$type = MushroomBlockTypeIdMap::getInstance()->fromId($type);
|
||||
@ -288,13 +283,6 @@ final class BlockStateDeserializerHelper{
|
||||
return $block;
|
||||
}
|
||||
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function decodeWallCoralFan(WallCoralFan $block, BlockStateReader $in) : WallCoralFan{
|
||||
return $block
|
||||
->setDead($in->readBool(BlockStateNames::DEAD_BIT))
|
||||
->setFacing($in->readCoralFacing());
|
||||
}
|
||||
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function decodeWallSign(WallSign $block, BlockStateReader $in) : WallSign{
|
||||
return $block
|
||||
@ -305,86 +293,4 @@ final class BlockStateDeserializerHelper{
|
||||
return $block
|
||||
->setOutputSignalStrength($in->readBoundedInt(BlockStateNames::REDSTONE_SIGNAL, 0, 15));
|
||||
}
|
||||
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function mapLegacyWallType(BlockStateReader $in) : Wall{
|
||||
return self::decodeWall(match($type = $in->readString(BlockStateNames::WALL_BLOCK_TYPE)){
|
||||
StringValues::WALL_BLOCK_TYPE_ANDESITE => VanillaBlocks::ANDESITE_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_BRICK => VanillaBlocks::BRICK_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_COBBLESTONE => VanillaBlocks::COBBLESTONE_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_DIORITE => VanillaBlocks::DIORITE_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_END_BRICK => VanillaBlocks::END_STONE_BRICK_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_GRANITE => VanillaBlocks::GRANITE_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_MOSSY_COBBLESTONE => VanillaBlocks::MOSSY_COBBLESTONE_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_MOSSY_STONE_BRICK => VanillaBlocks::MOSSY_STONE_BRICK_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_NETHER_BRICK => VanillaBlocks::NETHER_BRICK_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_PRISMARINE => VanillaBlocks::PRISMARINE_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_RED_NETHER_BRICK => VanillaBlocks::RED_NETHER_BRICK_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_RED_SANDSTONE => VanillaBlocks::RED_SANDSTONE_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_SANDSTONE => VanillaBlocks::SANDSTONE_WALL(),
|
||||
StringValues::WALL_BLOCK_TYPE_STONE_BRICK => VanillaBlocks::STONE_BRICK_WALL(),
|
||||
default => throw $in->badValueException(BlockStateNames::WALL_BLOCK_TYPE, $type),
|
||||
}, $in);
|
||||
}
|
||||
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function mapStoneSlab1Type(BlockStateReader $in) : Slab{
|
||||
//* stone_slab_type (StringTag) = brick, cobblestone, nether_brick, quartz, sandstone, smooth_stone, stone_brick, wood
|
||||
return match($type = $in->readString(BlockStateNames::STONE_SLAB_TYPE)){
|
||||
StringValues::STONE_SLAB_TYPE_BRICK => VanillaBlocks::BRICK_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_COBBLESTONE => VanillaBlocks::COBBLESTONE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_NETHER_BRICK => VanillaBlocks::NETHER_BRICK_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_QUARTZ => VanillaBlocks::QUARTZ_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_SANDSTONE => VanillaBlocks::SANDSTONE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_SMOOTH_STONE => VanillaBlocks::SMOOTH_STONE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_STONE_BRICK => VanillaBlocks::STONE_BRICK_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_WOOD => VanillaBlocks::FAKE_WOODEN_SLAB(),
|
||||
default => throw $in->badValueException(BlockStateNames::STONE_SLAB_TYPE, $type),
|
||||
};
|
||||
}
|
||||
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function mapStoneSlab2Type(BlockStateReader $in) : Slab{
|
||||
// * stone_slab_type_2 (StringTag) = mossy_cobblestone, prismarine_brick, prismarine_dark, prismarine_rough, purpur, red_nether_brick, red_sandstone, smooth_sandstone
|
||||
return match($type = $in->readString(BlockStateNames::STONE_SLAB_TYPE_2)){
|
||||
StringValues::STONE_SLAB_TYPE_2_MOSSY_COBBLESTONE => VanillaBlocks::MOSSY_COBBLESTONE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_2_PRISMARINE_BRICK => VanillaBlocks::PRISMARINE_BRICKS_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_2_PRISMARINE_DARK => VanillaBlocks::DARK_PRISMARINE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_2_PRISMARINE_ROUGH => VanillaBlocks::PRISMARINE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_2_PURPUR => VanillaBlocks::PURPUR_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_2_RED_NETHER_BRICK => VanillaBlocks::RED_NETHER_BRICK_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_2_RED_SANDSTONE => VanillaBlocks::RED_SANDSTONE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_2_SMOOTH_SANDSTONE => VanillaBlocks::SMOOTH_SANDSTONE_SLAB(),
|
||||
default => throw $in->badValueException(BlockStateNames::STONE_SLAB_TYPE_2, $type),
|
||||
};
|
||||
}
|
||||
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function mapStoneSlab3Type(BlockStateReader $in) : Slab{
|
||||
// * stone_slab_type_3 (StringTag) = andesite, diorite, end_stone_brick, granite, polished_andesite, polished_diorite, polished_granite, smooth_red_sandstone
|
||||
return match($type = $in->readString(BlockStateNames::STONE_SLAB_TYPE_3)){
|
||||
StringValues::STONE_SLAB_TYPE_3_ANDESITE => VanillaBlocks::ANDESITE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_3_DIORITE => VanillaBlocks::DIORITE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_3_END_STONE_BRICK => VanillaBlocks::END_STONE_BRICK_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_3_GRANITE => VanillaBlocks::GRANITE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_3_POLISHED_ANDESITE => VanillaBlocks::POLISHED_ANDESITE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_3_POLISHED_DIORITE => VanillaBlocks::POLISHED_DIORITE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_3_POLISHED_GRANITE => VanillaBlocks::POLISHED_GRANITE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_3_SMOOTH_RED_SANDSTONE => VanillaBlocks::SMOOTH_RED_SANDSTONE_SLAB(),
|
||||
default => throw $in->badValueException(BlockStateNames::STONE_SLAB_TYPE_3, $type),
|
||||
};
|
||||
}
|
||||
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function mapStoneSlab4Type(BlockStateReader $in) : Slab{
|
||||
// * stone_slab_type_4 (StringTag) = cut_red_sandstone, cut_sandstone, mossy_stone_brick, smooth_quartz, stone
|
||||
return match($type = $in->readString(BlockStateNames::STONE_SLAB_TYPE_4)){
|
||||
StringValues::STONE_SLAB_TYPE_4_CUT_RED_SANDSTONE => VanillaBlocks::CUT_RED_SANDSTONE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_4_CUT_SANDSTONE => VanillaBlocks::CUT_SANDSTONE_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_4_MOSSY_STONE_BRICK => VanillaBlocks::MOSSY_STONE_BRICK_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_4_SMOOTH_QUARTZ => VanillaBlocks::SMOOTH_QUARTZ_SLAB(),
|
||||
StringValues::STONE_SLAB_TYPE_4_STONE => VanillaBlocks::STONE_SLAB(),
|
||||
default => throw $in->badValueException(BlockStateNames::STONE_SLAB_TYPE_4, $type),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -68,9 +68,8 @@ final class BlockStateSerializerHelper{
|
||||
->writeInt(StateNames::CANDLES, $block->getCount() - 1);
|
||||
}
|
||||
|
||||
public static function encodeChemistryTable(ChemistryTable $block, string $chemistryTableType, Writer $out) : Writer{
|
||||
public static function encodeChemistryTable(ChemistryTable $block, Writer $out) : Writer{
|
||||
return $out
|
||||
->writeString(BlockStateNames::CHEMISTRY_TABLE_TYPE, $chemistryTableType)
|
||||
->writeLegacyHorizontalFacing(Facing::opposite($block->getFacing()));
|
||||
}
|
||||
|
||||
@ -78,9 +77,8 @@ final class BlockStateSerializerHelper{
|
||||
return $out->writeInt(BlockStateNames::GROWTH, $block->getAge());
|
||||
}
|
||||
|
||||
public static function encodeColoredTorch(Torch $block, bool $highBit, Writer $out) : Writer{
|
||||
public static function encodeTorch(Torch $block, Writer $out) : Writer{
|
||||
return $out
|
||||
->writeBool(BlockStateNames::COLOR_BIT, $highBit)
|
||||
->writeTorchFacing($block->getFacing());
|
||||
}
|
||||
|
||||
@ -160,16 +158,11 @@ final class BlockStateSerializerHelper{
|
||||
->writeInt(BlockStateNames::HUGE_MUSHROOM_BITS, MushroomBlockTypeIdMap::getInstance()->toId($block->getMushroomBlockType()));
|
||||
}
|
||||
|
||||
public static function encodeQuartz(string $type, int $axis) : Writer{
|
||||
return Writer::create(Ids::QUARTZ_BLOCK)
|
||||
->writeString(BlockStateNames::CHISEL_TYPE, $type)
|
||||
public static function encodeQuartz(int $axis, Writer $out) : Writer{
|
||||
return $out
|
||||
->writePillarAxis($axis); //this isn't needed for all types, but we have to write it anyway
|
||||
}
|
||||
|
||||
public static function encodeSandstone(string $id, string $type) : Writer{
|
||||
return Writer::create($id)->writeString(BlockStateNames::SAND_STONE_TYPE, $type);
|
||||
}
|
||||
|
||||
public static function encodeSapling(Sapling $block, Writer $out) : Writer{
|
||||
return $out
|
||||
->writeBool(BlockStateNames::AGE_BIT, $block->isReady());
|
||||
@ -214,36 +207,6 @@ final class BlockStateSerializerHelper{
|
||||
->writeFacingWithoutUp($facing === Facing::UP ? Facing::DOWN : $facing);
|
||||
}
|
||||
|
||||
public static function encodeStoneBricks(string $type) : Writer{
|
||||
return Writer::create(Ids::STONEBRICK)
|
||||
->writeString(BlockStateNames::STONE_BRICK_TYPE, $type);
|
||||
}
|
||||
|
||||
private static function encodeStoneSlab(Slab $block, string $singleId, string $doubleId, string $typeKey, string $typeValue) : Writer{
|
||||
return self::encodeSlab($block, $singleId, $doubleId)
|
||||
->writeString($typeKey, $typeValue);
|
||||
}
|
||||
|
||||
public static function encodeStoneSlab1(Slab $block, string $singleId, string $doubleTypeValue) : Writer{
|
||||
//1.21 made this a mess by flattening single slab IDs but not double ones
|
||||
return $block->getSlabType() === SlabType::DOUBLE ?
|
||||
self::encodeDoubleSlab($block, Ids::DOUBLE_STONE_BLOCK_SLAB)
|
||||
->writeString(BlockStateNames::STONE_SLAB_TYPE, $doubleTypeValue) :
|
||||
self::encodeSingleSlab($block, $singleId);
|
||||
}
|
||||
|
||||
public static function encodeStoneSlab2(Slab $block, string $typeValue) : Writer{
|
||||
return self::encodeStoneSlab($block, Ids::STONE_BLOCK_SLAB2, Ids::DOUBLE_STONE_BLOCK_SLAB2, BlockStateNames::STONE_SLAB_TYPE_2, $typeValue);
|
||||
}
|
||||
|
||||
public static function encodeStoneSlab3(Slab $block, string $typeValue) : Writer{
|
||||
return self::encodeStoneSlab($block, Ids::STONE_BLOCK_SLAB3, Ids::DOUBLE_STONE_BLOCK_SLAB3, BlockStateNames::STONE_SLAB_TYPE_3, $typeValue);
|
||||
}
|
||||
|
||||
public static function encodeStoneSlab4(Slab $block, string $typeValue) : Writer{
|
||||
return self::encodeStoneSlab($block, Ids::STONE_BLOCK_SLAB4, Ids::DOUBLE_STONE_BLOCK_SLAB4, BlockStateNames::STONE_SLAB_TYPE_4, $typeValue);
|
||||
}
|
||||
|
||||
public static function encodeTrapdoor(Trapdoor $block, Writer $out) : Writer{
|
||||
return $out
|
||||
->write5MinusHorizontalFacing($block->getFacing())
|
||||
@ -260,11 +223,6 @@ final class BlockStateSerializerHelper{
|
||||
->writeWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_WEST, $block->getConnection(Facing::WEST));
|
||||
}
|
||||
|
||||
public static function encodeLegacyWall(Wall $block, string $type) : Writer{
|
||||
return self::encodeWall($block, Writer::create(Ids::COBBLESTONE_WALL))
|
||||
->writeString(BlockStateNames::WALL_BLOCK_TYPE, $type);
|
||||
}
|
||||
|
||||
public static function encodeWallSign(WallSign $block, Writer $out) : Writer{
|
||||
return $out
|
||||
->writeHorizontalFacing($block->getFacing());
|
||||
|
@ -24,12 +24,13 @@ declare(strict_types=1);
|
||||
namespace pocketmine\data\bedrock\block\convert;
|
||||
|
||||
use pocketmine\block\AmethystCluster;
|
||||
use pocketmine\block\Anvil;
|
||||
use pocketmine\block\Bamboo;
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\CaveVines;
|
||||
use pocketmine\block\ChorusFlower;
|
||||
use pocketmine\block\DoublePitcherCrop;
|
||||
use pocketmine\block\Light;
|
||||
use pocketmine\block\Opaque;
|
||||
use pocketmine\block\PinkPetals;
|
||||
use pocketmine\block\PitcherCrop;
|
||||
use pocketmine\block\Slab;
|
||||
@ -44,6 +45,7 @@ use pocketmine\block\utils\DripleafState;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\block\utils\FroglightType;
|
||||
use pocketmine\block\utils\LeverFacing;
|
||||
use pocketmine\block\utils\MobHeadType;
|
||||
use pocketmine\block\VanillaBlocks as Blocks;
|
||||
use pocketmine\block\Wood;
|
||||
use pocketmine\data\bedrock\block\BlockLegacyMetadata;
|
||||
@ -83,6 +85,8 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->registerFlatWoodBlockDeserializers();
|
||||
$this->registerLeavesDeserializers();
|
||||
$this->registerSaplingDeserializers();
|
||||
$this->registerLightDeserializers();
|
||||
$this->registerMobHeadDeserializers();
|
||||
$this->registerSimpleDeserializers();
|
||||
$this->registerDeserializers();
|
||||
}
|
||||
@ -457,6 +461,17 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map($aliveId, fn(Reader $in) => Blocks::CORAL_BLOCK()->setCoralType($coralType)->setDead(false));
|
||||
$this->map($deadId, fn(Reader $in) => Blocks::CORAL_BLOCK()->setCoralType($coralType)->setDead(true));
|
||||
}
|
||||
|
||||
foreach([
|
||||
[CoralType::BRAIN, Ids::BRAIN_CORAL_WALL_FAN, Ids::DEAD_BRAIN_CORAL_WALL_FAN],
|
||||
[CoralType::BUBBLE, Ids::BUBBLE_CORAL_WALL_FAN, Ids::DEAD_BUBBLE_CORAL_WALL_FAN],
|
||||
[CoralType::FIRE, Ids::FIRE_CORAL_WALL_FAN, Ids::DEAD_FIRE_CORAL_WALL_FAN],
|
||||
[CoralType::HORN, Ids::HORN_CORAL_WALL_FAN, Ids::DEAD_HORN_CORAL_WALL_FAN],
|
||||
[CoralType::TUBE, Ids::TUBE_CORAL_WALL_FAN, Ids::DEAD_TUBE_CORAL_WALL_FAN],
|
||||
] as [$coralType, $aliveId, $deadId]){
|
||||
$this->map($aliveId, fn(Reader $in) => Blocks::WALL_CORAL_FAN()->setFacing($in->readCoralFacing())->setCoralType($coralType)->setDead(false));
|
||||
$this->map($deadId, fn(Reader $in) => Blocks::WALL_CORAL_FAN()->setFacing($in->readCoralFacing())->setCoralType($coralType)->setDead(true));
|
||||
}
|
||||
}
|
||||
|
||||
private function registerCauldronDeserializers() : void{
|
||||
@ -518,10 +533,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::CHERRY_PLANKS, fn() => Blocks::CHERRY_PLANKS());
|
||||
$this->mapSlab(Ids::CHERRY_SLAB, Ids::CHERRY_DOUBLE_SLAB, fn() => Blocks::CHERRY_SLAB());
|
||||
$this->mapStairs(Ids::CHERRY_STAIRS, fn() => Blocks::CHERRY_STAIRS());
|
||||
$this->map(Ids::CHERRY_WOOD, function(Reader $in){
|
||||
$in->ignored(StateNames::STRIPPED_BIT); //this is also ignored by vanilla
|
||||
return Helper::decodeLog(Blocks::CHERRY_WOOD(), false, $in);
|
||||
});
|
||||
$this->map(Ids::CHERRY_WOOD, fn(Reader $in) => Helper::decodeLog(Blocks::CHERRY_WOOD(), false, $in));
|
||||
$this->map(Ids::STRIPPED_CHERRY_WOOD, fn(Reader $in) => Helper::decodeLog(Blocks::CHERRY_WOOD(), true, $in));
|
||||
|
||||
$this->map(Ids::CRIMSON_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::CRIMSON_BUTTON(), $in));
|
||||
@ -578,10 +590,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::MANGROVE_PLANKS, fn() => Blocks::MANGROVE_PLANKS());
|
||||
$this->mapSlab(Ids::MANGROVE_SLAB, Ids::MANGROVE_DOUBLE_SLAB, fn() => Blocks::MANGROVE_SLAB());
|
||||
$this->mapStairs(Ids::MANGROVE_STAIRS, fn() => Blocks::MANGROVE_STAIRS());
|
||||
$this->map(Ids::MANGROVE_WOOD, function(Reader $in){
|
||||
$in->ignored(StateNames::STRIPPED_BIT); //this is also ignored by vanilla
|
||||
return Helper::decodeLog(Blocks::MANGROVE_WOOD(), false, $in);
|
||||
});
|
||||
$this->map(Ids::MANGROVE_WOOD, fn(Reader $in) => Helper::decodeLog(Blocks::MANGROVE_WOOD(), false, $in));
|
||||
$this->map(Ids::STRIPPED_MANGROVE_WOOD, fn(Reader $in) => Helper::decodeLog(Blocks::MANGROVE_WOOD(), true, $in));
|
||||
|
||||
//oak - due to age, many of these don't specify "oak", making for confusing reading
|
||||
@ -654,6 +663,43 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
}
|
||||
}
|
||||
|
||||
private function registerLightDeserializers() : void{
|
||||
foreach([
|
||||
Ids::LIGHT_BLOCK_0 => 0,
|
||||
Ids::LIGHT_BLOCK_1 => 1,
|
||||
Ids::LIGHT_BLOCK_2 => 2,
|
||||
Ids::LIGHT_BLOCK_3 => 3,
|
||||
Ids::LIGHT_BLOCK_4 => 4,
|
||||
Ids::LIGHT_BLOCK_5 => 5,
|
||||
Ids::LIGHT_BLOCK_6 => 6,
|
||||
Ids::LIGHT_BLOCK_7 => 7,
|
||||
Ids::LIGHT_BLOCK_8 => 8,
|
||||
Ids::LIGHT_BLOCK_9 => 9,
|
||||
Ids::LIGHT_BLOCK_10 => 10,
|
||||
Ids::LIGHT_BLOCK_11 => 11,
|
||||
Ids::LIGHT_BLOCK_12 => 12,
|
||||
Ids::LIGHT_BLOCK_13 => 13,
|
||||
Ids::LIGHT_BLOCK_14 => 14,
|
||||
Ids::LIGHT_BLOCK_15 => 15,
|
||||
] as $id => $level){
|
||||
$this->mapSimple($id, fn() => Blocks::LIGHT()->setLightLevel($level));
|
||||
}
|
||||
}
|
||||
|
||||
private function registerMobHeadDeserializers() : void{
|
||||
foreach([
|
||||
Ids::CREEPER_HEAD => MobHeadType::CREEPER,
|
||||
Ids::DRAGON_HEAD => MobHeadType::DRAGON,
|
||||
Ids::PIGLIN_HEAD => MobHeadType::PIGLIN,
|
||||
Ids::PLAYER_HEAD => MobHeadType::PLAYER,
|
||||
Ids::SKELETON_SKULL => MobHeadType::SKELETON,
|
||||
Ids::WITHER_SKELETON_SKULL => MobHeadType::WITHER_SKELETON,
|
||||
Ids::ZOMBIE_HEAD => MobHeadType::ZOMBIE
|
||||
] as $id => $mobHeadType){
|
||||
$this->map($id, fn(Reader $in) => Blocks::MOB_HEAD()->setMobHeadType($mobHeadType)->setFacing($in->readFacingWithoutDown()));
|
||||
}
|
||||
}
|
||||
|
||||
private function registerSimpleDeserializers() : void{
|
||||
$this->mapSimple(Ids::AIR, fn() => Blocks::AIR());
|
||||
$this->mapSimple(Ids::AMETHYST_BLOCK, fn() => Blocks::AMETHYST());
|
||||
@ -673,6 +719,11 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::CHISELED_DEEPSLATE, fn() => Blocks::CHISELED_DEEPSLATE());
|
||||
$this->mapSimple(Ids::CHISELED_NETHER_BRICKS, fn() => Blocks::CHISELED_NETHER_BRICKS());
|
||||
$this->mapSimple(Ids::CHISELED_POLISHED_BLACKSTONE, fn() => Blocks::CHISELED_POLISHED_BLACKSTONE());
|
||||
$this->mapSimple(Ids::CHISELED_RED_SANDSTONE, fn() => Blocks::CHISELED_RED_SANDSTONE());
|
||||
$this->mapSimple(Ids::CHISELED_SANDSTONE, fn() => Blocks::CHISELED_SANDSTONE());
|
||||
$this->mapSimple(Ids::CHISELED_STONE_BRICKS, fn() => Blocks::CHISELED_STONE_BRICKS());
|
||||
$this->mapSimple(Ids::CHISELED_TUFF, fn() => Blocks::CHISELED_TUFF());
|
||||
$this->mapSimple(Ids::CHISELED_TUFF_BRICKS, fn() => Blocks::CHISELED_TUFF_BRICKS());
|
||||
$this->mapSimple(Ids::CHORUS_PLANT, fn() => Blocks::CHORUS_PLANT());
|
||||
$this->mapSimple(Ids::CLAY, fn() => Blocks::CLAY());
|
||||
$this->mapSimple(Ids::COAL_BLOCK, fn() => Blocks::COAL());
|
||||
@ -684,9 +735,13 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::CRACKED_DEEPSLATE_TILES, fn() => Blocks::CRACKED_DEEPSLATE_TILES());
|
||||
$this->mapSimple(Ids::CRACKED_NETHER_BRICKS, fn() => Blocks::CRACKED_NETHER_BRICKS());
|
||||
$this->mapSimple(Ids::CRACKED_POLISHED_BLACKSTONE_BRICKS, fn() => Blocks::CRACKED_POLISHED_BLACKSTONE_BRICKS());
|
||||
$this->mapSimple(Ids::CRACKED_STONE_BRICKS, fn() => Blocks::CRACKED_STONE_BRICKS());
|
||||
$this->mapSimple(Ids::CRAFTING_TABLE, fn() => Blocks::CRAFTING_TABLE());
|
||||
$this->mapSimple(Ids::CRIMSON_ROOTS, fn() => Blocks::CRIMSON_ROOTS());
|
||||
$this->mapSimple(Ids::CRYING_OBSIDIAN, fn() => Blocks::CRYING_OBSIDIAN());
|
||||
$this->mapSimple(Ids::CUT_RED_SANDSTONE, fn() => Blocks::CUT_RED_SANDSTONE());
|
||||
$this->mapSimple(Ids::CUT_SANDSTONE, fn() => Blocks::CUT_SANDSTONE());
|
||||
$this->mapSimple(Ids::DARK_PRISMARINE, fn() => Blocks::DARK_PRISMARINE());
|
||||
$this->mapSimple(Ids::DEADBUSH, fn() => Blocks::DEAD_BUSH());
|
||||
$this->mapSimple(Ids::DEEPSLATE_BRICKS, fn() => Blocks::DEEPSLATE_BRICKS());
|
||||
$this->mapSimple(Ids::DEEPSLATE_COAL_ORE, fn() => Blocks::DEEPSLATE_COAL_ORE());
|
||||
@ -845,6 +900,12 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::HARDENED_CLAY, fn() => Blocks::HARDENED_CLAY());
|
||||
$this->mapSimple(Ids::HONEYCOMB_BLOCK, fn() => Blocks::HONEYCOMB());
|
||||
$this->mapSimple(Ids::ICE, fn() => Blocks::ICE());
|
||||
$this->mapSimple(Ids::INFESTED_CHISELED_STONE_BRICKS, fn() => Blocks::INFESTED_CHISELED_STONE_BRICK());
|
||||
$this->mapSimple(Ids::INFESTED_COBBLESTONE, fn() => Blocks::INFESTED_COBBLESTONE());
|
||||
$this->mapSimple(Ids::INFESTED_CRACKED_STONE_BRICKS, fn() => Blocks::INFESTED_CRACKED_STONE_BRICK());
|
||||
$this->mapSimple(Ids::INFESTED_MOSSY_STONE_BRICKS, fn() => Blocks::INFESTED_MOSSY_STONE_BRICK());
|
||||
$this->mapSimple(Ids::INFESTED_STONE, fn() => Blocks::INFESTED_STONE());
|
||||
$this->mapSimple(Ids::INFESTED_STONE_BRICKS, fn() => Blocks::INFESTED_STONE_BRICK());
|
||||
$this->mapSimple(Ids::INFO_UPDATE, fn() => Blocks::INFO_UPDATE());
|
||||
$this->mapSimple(Ids::INFO_UPDATE2, fn() => Blocks::INFO_UPDATE2());
|
||||
$this->mapSimple(Ids::INVISIBLE_BEDROCK, fn() => Blocks::INVISIBLE_BEDROCK());
|
||||
@ -859,6 +920,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::MELON_BLOCK, fn() => Blocks::MELON());
|
||||
$this->mapSimple(Ids::MOB_SPAWNER, fn() => Blocks::MONSTER_SPAWNER());
|
||||
$this->mapSimple(Ids::MOSSY_COBBLESTONE, fn() => Blocks::MOSSY_COBBLESTONE());
|
||||
$this->mapSimple(Ids::MOSSY_STONE_BRICKS, fn() => Blocks::MOSSY_STONE_BRICKS());
|
||||
$this->mapSimple(Ids::MUD, fn() => Blocks::MUD());
|
||||
$this->mapSimple(Ids::MUD_BRICKS, fn() => Blocks::MUD_BRICKS());
|
||||
$this->mapSimple(Ids::MYCELIUM, fn() => Blocks::MYCELIUM());
|
||||
@ -880,6 +942,9 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$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::POLISHED_TUFF, fn() => Blocks::POLISHED_TUFF());
|
||||
$this->mapSimple(Ids::PRISMARINE, fn() => Blocks::PRISMARINE());
|
||||
$this->mapSimple(Ids::PRISMARINE_BRICKS, fn() => Blocks::PRISMARINE_BRICKS());
|
||||
$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());
|
||||
@ -887,9 +952,13 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::RAW_IRON_BLOCK, fn() => Blocks::RAW_IRON());
|
||||
$this->mapSimple(Ids::RED_MUSHROOM, fn() => Blocks::RED_MUSHROOM());
|
||||
$this->mapSimple(Ids::RED_NETHER_BRICK, fn() => Blocks::RED_NETHER_BRICKS());
|
||||
$this->mapSimple(Ids::RED_SAND, fn() => Blocks::RED_SAND());
|
||||
$this->mapSimple(Ids::RED_SANDSTONE, fn() => Blocks::RED_SANDSTONE());
|
||||
$this->mapSimple(Ids::REDSTONE_BLOCK, fn() => Blocks::REDSTONE());
|
||||
$this->mapSimple(Ids::REINFORCED_DEEPSLATE, fn() => Blocks::REINFORCED_DEEPSLATE());
|
||||
$this->mapSimple(Ids::RESERVED6, fn() => Blocks::RESERVED6());
|
||||
$this->mapSimple(Ids::SAND, fn() => Blocks::SAND());
|
||||
$this->mapSimple(Ids::SANDSTONE, fn() => Blocks::SANDSTONE());
|
||||
$this->mapSimple(Ids::SCULK, fn() => Blocks::SCULK());
|
||||
$this->mapSimple(Ids::SEA_LANTERN, fn() => Blocks::SEA_LANTERN());
|
||||
$this->mapSimple(Ids::SHORT_GRASS, fn() => Blocks::TALL_GRASS()); //no, this is not a typo - tall_grass is now the double block, just to be confusing :(
|
||||
@ -897,23 +966,29 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSimple(Ids::SLIME, fn() => Blocks::SLIME());
|
||||
$this->mapSimple(Ids::SMITHING_TABLE, fn() => Blocks::SMITHING_TABLE());
|
||||
$this->mapSimple(Ids::SMOOTH_BASALT, fn() => Blocks::SMOOTH_BASALT());
|
||||
$this->mapSimple(Ids::SMOOTH_RED_SANDSTONE, fn() => Blocks::SMOOTH_RED_SANDSTONE());
|
||||
$this->mapSimple(Ids::SMOOTH_SANDSTONE, fn() => Blocks::SMOOTH_SANDSTONE());
|
||||
$this->mapSimple(Ids::SMOOTH_STONE, fn() => Blocks::SMOOTH_STONE());
|
||||
$this->mapSimple(Ids::SNOW, fn() => Blocks::SNOW());
|
||||
$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::SPONGE, fn() => Blocks::SPONGE());
|
||||
$this->mapSimple(Ids::STONE, fn() => Blocks::STONE());
|
||||
$this->mapSimple(Ids::STONECUTTER, fn() => Blocks::LEGACY_STONECUTTER());
|
||||
$this->mapSimple(Ids::STONE_BRICKS, fn() => Blocks::STONE_BRICKS());
|
||||
$this->mapSimple(Ids::TINTED_GLASS, fn() => Blocks::TINTED_GLASS());
|
||||
$this->mapSimple(Ids::TORCHFLOWER, fn() => Blocks::TORCHFLOWER());
|
||||
$this->mapSimple(Ids::TUFF, fn() => Blocks::TUFF());
|
||||
$this->mapSimple(Ids::TUFF_BRICKS, fn() => Blocks::TUFF_BRICKS());
|
||||
$this->mapSimple(Ids::UNDYED_SHULKER_BOX, fn() => Blocks::SHULKER_BOX());
|
||||
$this->mapSimple(Ids::WARPED_WART_BLOCK, fn() => Blocks::WARPED_WART_BLOCK());
|
||||
$this->mapSimple(Ids::WARPED_ROOTS, fn() => Blocks::WARPED_ROOTS());
|
||||
$this->mapSimple(Ids::WATERLILY, fn() => Blocks::LILY_PAD());
|
||||
$this->mapSimple(Ids::WEB, fn() => Blocks::COBWEB());
|
||||
$this->mapSimple(Ids::WET_SPONGE, fn() => Blocks::SPONGE()->setWet(true));
|
||||
$this->mapSimple(Ids::WITHER_ROSE, fn() => Blocks::WITHER_ROSE());
|
||||
$this->mapSimple(Ids::YELLOW_FLOWER, fn() => Blocks::DANDELION());
|
||||
$this->mapSimple(Ids::DANDELION, fn() => Blocks::DANDELION());
|
||||
|
||||
$this->mapSimple(Ids::ALLIUM, fn() => Blocks::ALLIUM());
|
||||
$this->mapSimple(Ids::CORNFLOWER, fn() => Blocks::CORNFLOWER());
|
||||
@ -939,16 +1014,22 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
->setStage(AmethystCluster::STAGE_CLUSTER)
|
||||
->setFacing($in->readBlockFace());
|
||||
});
|
||||
$this->mapSlab(Ids::ANDESITE_SLAB, Ids::ANDESITE_DOUBLE_SLAB, fn() => Blocks::ANDESITE_SLAB());
|
||||
$this->mapStairs(Ids::ANDESITE_STAIRS, fn() => Blocks::ANDESITE_STAIRS());
|
||||
$this->map(Ids::ANDESITE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::ANDESITE_WALL(), $in));
|
||||
$this->map(Ids::ANVIL, function(Reader $in) : Block{
|
||||
return Blocks::ANVIL()
|
||||
->setDamage(match($value = $in->readString(StateNames::DAMAGE)){
|
||||
StringValues::DAMAGE_UNDAMAGED => 0,
|
||||
StringValues::DAMAGE_SLIGHTLY_DAMAGED => 1,
|
||||
StringValues::DAMAGE_VERY_DAMAGED => 2,
|
||||
StringValues::DAMAGE_BROKEN => 0,
|
||||
default => throw $in->badValueException(StateNames::DAMAGE, $value),
|
||||
})
|
||||
->setDamage(Anvil::UNDAMAGED)
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::CHIPPED_ANVIL, function(Reader $in) : Block{
|
||||
return Blocks::ANVIL()
|
||||
->setDamage(Anvil::SLIGHTLY_DAMAGED)
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::DAMAGED_ANVIL, function(Reader $in) : Block{
|
||||
return Blocks::ANVIL()
|
||||
->setDamage(Anvil::VERY_DAMAGED)
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::BAMBOO, function(Reader $in) : Block{
|
||||
@ -1029,7 +1110,14 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
->setSlot(BrewingStandSlot::SOUTHWEST, $in->readBool(StateNames::BREWING_STAND_SLOT_B_BIT))
|
||||
->setSlot(BrewingStandSlot::NORTHWEST, $in->readBool(StateNames::BREWING_STAND_SLOT_C_BIT));
|
||||
});
|
||||
$this->mapSlab(Ids::BRICK_SLAB, Ids::BRICK_DOUBLE_SLAB, fn() => Blocks::BRICK_SLAB());
|
||||
$this->mapStairs(Ids::BRICK_STAIRS, fn() => Blocks::BRICK_STAIRS());
|
||||
$this->map(Ids::BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::BRICK_WALL(), $in));
|
||||
$this->map(Ids::MUSHROOM_STEM, fn(Reader $in) => match($in->readBoundedInt(StateNames::HUGE_MUSHROOM_BITS, 0, 15)){
|
||||
BlockLegacyMetadata::MUSHROOM_BLOCK_ALL_STEM => Blocks::ALL_SIDED_MUSHROOM_STEM(),
|
||||
BlockLegacyMetadata::MUSHROOM_BLOCK_STEM => Blocks::MUSHROOM_STEM(),
|
||||
default => throw new BlockStateDeserializeException("This state does not exist"),
|
||||
});
|
||||
$this->map(Ids::BROWN_MUSHROOM_BLOCK, fn(Reader $in) => Helper::decodeMushroomBlock(Blocks::BROWN_MUSHROOM_BLOCK(), $in));
|
||||
$this->map(Ids::CACTUS, function(Reader $in) : Block{
|
||||
return Blocks::CACTUS()
|
||||
@ -1039,6 +1127,11 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
return Blocks::CAKE()
|
||||
->setBites($in->readBoundedInt(StateNames::BITE_COUNTER, 0, 6));
|
||||
});
|
||||
$this->map(Ids::CAMPFIRE, function(Reader $in) : Block{
|
||||
return Blocks::CAMPFIRE()
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setLit(!$in->readBool(StateNames::EXTINGUISHED));
|
||||
});
|
||||
$this->map(Ids::CARROTS, fn(Reader $in) => Helper::decodeCrops(Blocks::CARROTS(), $in));
|
||||
$this->map(Ids::CARVED_PUMPKIN, function(Reader $in) : Block{
|
||||
return Blocks::CARVED_PUMPKIN()
|
||||
@ -1078,14 +1171,10 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
|
||||
return $block;
|
||||
});
|
||||
$this->map(Ids::CHEMISTRY_TABLE, function(Reader $in) : Block{
|
||||
return (match($type = $in->readString(StateNames::CHEMISTRY_TABLE_TYPE)){
|
||||
StringValues::CHEMISTRY_TABLE_TYPE_COMPOUND_CREATOR => Blocks::COMPOUND_CREATOR(),
|
||||
StringValues::CHEMISTRY_TABLE_TYPE_ELEMENT_CONSTRUCTOR => Blocks::ELEMENT_CONSTRUCTOR(),
|
||||
StringValues::CHEMISTRY_TABLE_TYPE_LAB_TABLE => Blocks::LAB_TABLE(),
|
||||
StringValues::CHEMISTRY_TABLE_TYPE_MATERIAL_REDUCER => Blocks::MATERIAL_REDUCER(),
|
||||
default => throw $in->badValueException(StateNames::CHEMISTRY_TABLE_TYPE, $type),
|
||||
})->setFacing(Facing::opposite($in->readLegacyHorizontalFacing()));
|
||||
$this->map(Ids::CHISELED_COPPER, fn() => Helper::decodeCopper(Blocks::CHISELED_COPPER(), CopperOxidation::NONE));
|
||||
$this->map(Ids::CHISELED_QUARTZ_BLOCK, function(Reader $in) : Block{
|
||||
return Blocks::CHISELED_QUARTZ()
|
||||
->setAxis($in->readPillarAxis());
|
||||
});
|
||||
$this->map(Ids::CHEST, function(Reader $in) : Block{
|
||||
return Blocks::CHEST()
|
||||
@ -1095,38 +1184,39 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
return Blocks::CHORUS_FLOWER()
|
||||
->setAge($in->readBoundedInt(StateNames::AGE, ChorusFlower::MIN_AGE, ChorusFlower::MAX_AGE));
|
||||
});
|
||||
$this->map(Ids::COARSE_DIRT, fn() => Blocks::DIRT()->setDirtType(DirtType::COARSE));
|
||||
$this->mapSlab(Ids::COBBLED_DEEPSLATE_SLAB, Ids::COBBLED_DEEPSLATE_DOUBLE_SLAB, fn() => Blocks::COBBLED_DEEPSLATE_SLAB());
|
||||
$this->mapStairs(Ids::COBBLED_DEEPSLATE_STAIRS, fn() => Blocks::COBBLED_DEEPSLATE_STAIRS());
|
||||
$this->map(Ids::COBBLED_DEEPSLATE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::COBBLED_DEEPSLATE_WALL(), $in));
|
||||
$this->map(Ids::COBBLESTONE_WALL, fn(Reader $in) => Helper::mapLegacyWallType($in));
|
||||
$this->mapSlab(Ids::COBBLESTONE_SLAB, Ids::COBBLESTONE_DOUBLE_SLAB, fn() => Blocks::COBBLESTONE_SLAB());
|
||||
$this->map(Ids::COBBLESTONE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::COBBLESTONE_WALL(), $in));
|
||||
$this->map(Ids::COCOA, function(Reader $in) : Block{
|
||||
return Blocks::COCOA_POD()
|
||||
->setAge($in->readBoundedInt(StateNames::AGE, 0, 2))
|
||||
->setFacing(Facing::opposite($in->readLegacyHorizontalFacing()));
|
||||
});
|
||||
$this->map(Ids::COLORED_TORCH_BP, function(Reader $in) : Block{
|
||||
return $in->readBool(StateNames::COLOR_BIT) ?
|
||||
Blocks::PURPLE_TORCH()->setFacing($in->readTorchFacing()) :
|
||||
Blocks::BLUE_TORCH()->setFacing($in->readTorchFacing());
|
||||
});
|
||||
$this->map(Ids::COLORED_TORCH_RG, function(Reader $in) : Block{
|
||||
return $in->readBool(StateNames::COLOR_BIT) ?
|
||||
Blocks::GREEN_TORCH()->setFacing($in->readTorchFacing()) :
|
||||
Blocks::RED_TORCH()->setFacing($in->readTorchFacing());
|
||||
});
|
||||
$this->map(Ids::COLORED_TORCH_BLUE, fn(Reader $in) => Blocks::BLUE_TORCH()->setFacing($in->readTorchFacing()));
|
||||
$this->map(Ids::COLORED_TORCH_GREEN, fn(Reader $in) => Blocks::GREEN_TORCH()->setFacing($in->readTorchFacing()));
|
||||
$this->map(Ids::COLORED_TORCH_PURPLE, fn(Reader $in) => Blocks::PURPLE_TORCH()->setFacing($in->readTorchFacing()));
|
||||
$this->map(Ids::COLORED_TORCH_RED, fn(Reader $in) => Blocks::RED_TORCH()->setFacing($in->readTorchFacing()));
|
||||
$this->map(Ids::COMPOUND_CREATOR, fn(Reader $in) => Blocks::COMPOUND_CREATOR()
|
||||
->setFacing(Facing::opposite($in->readLegacyHorizontalFacing()))
|
||||
);
|
||||
$this->map(Ids::COPPER_BLOCK, fn() => Helper::decodeCopper(Blocks::COPPER(), CopperOxidation::NONE));
|
||||
$this->map(Ids::COPPER_BULB, function(Reader $in) : Block{
|
||||
return Helper::decodeCopper(Blocks::COPPER_BULB(), CopperOxidation::NONE)
|
||||
->setLit($in->readBool(StateNames::LIT))
|
||||
->setPowered($in->readBool(StateNames::POWERED_BIT));
|
||||
});
|
||||
$this->map(Ids::COPPER_DOOR, fn(Reader $in) => Helper::decodeDoor(Helper::decodeCopper(Blocks::COPPER_DOOR(), CopperOxidation::NONE), $in));
|
||||
$this->map(Ids::COPPER_GRATE, fn() => Helper::decodeCopper(Blocks::COPPER_GRATE(), CopperOxidation::NONE));
|
||||
$this->map(Ids::COPPER_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Helper::decodeCopper(Blocks::COPPER_TRAPDOOR(), CopperOxidation::NONE), $in));
|
||||
$this->map(Ids::CUT_COPPER, fn() => Helper::decodeCopper(Blocks::CUT_COPPER(), CopperOxidation::NONE));
|
||||
$this->mapSlab(Ids::CUT_COPPER_SLAB, Ids::DOUBLE_CUT_COPPER_SLAB, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_SLAB(), CopperOxidation::NONE));
|
||||
$this->mapStairs(Ids::CUT_COPPER_STAIRS, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_STAIRS(), CopperOxidation::NONE));
|
||||
$this->map(Ids::CORAL_FAN_HANG, fn(Reader $in) => Helper::decodeWallCoralFan(Blocks::WALL_CORAL_FAN(), $in)
|
||||
->setCoralType($in->readBool(StateNames::CORAL_HANG_TYPE_BIT) ? CoralType::BRAIN : CoralType::TUBE));
|
||||
$this->map(Ids::CORAL_FAN_HANG2, fn(Reader $in) => Helper::decodeWallCoralFan(Blocks::WALL_CORAL_FAN(), $in)
|
||||
->setCoralType($in->readBool(StateNames::CORAL_HANG_TYPE_BIT) ? CoralType::FIRE : CoralType::BUBBLE));
|
||||
$this->map(Ids::CORAL_FAN_HANG3, function(Reader $in) : Block{
|
||||
$in->ignored(StateNames::CORAL_HANG_TYPE_BIT); //the game always writes this, even though it's not used
|
||||
return Helper::decodeWallCoralFan(Blocks::WALL_CORAL_FAN(), $in)
|
||||
->setCoralType(CoralType::HORN);
|
||||
});
|
||||
$this->mapSlab(Ids::CUT_RED_SANDSTONE_SLAB, Ids::CUT_RED_SANDSTONE_DOUBLE_SLAB, fn() => Blocks::CUT_RED_SANDSTONE_SLAB());
|
||||
$this->mapSlab(Ids::CUT_SANDSTONE_SLAB, Ids::CUT_SANDSTONE_DOUBLE_SLAB, fn() => Blocks::CUT_SANDSTONE_SLAB());
|
||||
$this->mapSlab(Ids::DARK_PRISMARINE_SLAB, Ids::DARK_PRISMARINE_DOUBLE_SLAB, fn() => Blocks::DARK_PRISMARINE_SLAB());
|
||||
$this->mapStairs(Ids::DARK_PRISMARINE_STAIRS, fn() => Blocks::DARK_PRISMARINE_STAIRS());
|
||||
$this->map(Ids::DAYLIGHT_DETECTOR, fn(Reader $in) => Helper::decodeDaylightSensor(Blocks::DAYLIGHT_SENSOR(), $in)
|
||||
->setInverted(false));
|
||||
@ -1148,15 +1238,10 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
->setActivated($in->readBool(StateNames::RAIL_DATA_BIT))
|
||||
->setShape($in->readBoundedInt(StateNames::RAIL_DIRECTION, 0, 5));
|
||||
});
|
||||
$this->mapSlab(Ids::DIORITE_SLAB, Ids::DIORITE_DOUBLE_SLAB, fn() => Blocks::DIORITE_SLAB());
|
||||
$this->mapStairs(Ids::DIORITE_STAIRS, fn() => Blocks::DIORITE_STAIRS());
|
||||
$this->map(Ids::DIRT, function(Reader $in) : Block{
|
||||
return Blocks::DIRT()
|
||||
->setDirtType(match($value = $in->readString(StateNames::DIRT_TYPE)){
|
||||
StringValues::DIRT_TYPE_NORMAL => DirtType::NORMAL,
|
||||
StringValues::DIRT_TYPE_COARSE => DirtType::COARSE,
|
||||
default => throw $in->badValueException(StateNames::DIRT_TYPE, $value),
|
||||
});
|
||||
});
|
||||
$this->map(Ids::DIORITE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::DIORITE_WALL(), $in));
|
||||
$this->map(Ids::DIRT, fn() => Blocks::DIRT()->setDirtType(DirtType::NORMAL));
|
||||
$this->map(Ids::DIRT_WITH_ROOTS, fn() => Blocks::DIRT()->setDirtType(DirtType::ROOTED));
|
||||
$this->map(Ids::LARGE_FERN, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::LARGE_FERN(), $in));
|
||||
$this->map(Ids::TALL_GRASS, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::DOUBLE_TALLGRASS(), $in));
|
||||
@ -1164,7 +1249,11 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::ROSE_BUSH, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::ROSE_BUSH(), $in));
|
||||
$this->map(Ids::SUNFLOWER, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::SUNFLOWER(), $in));
|
||||
$this->map(Ids::LILAC, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::LILAC(), $in));
|
||||
$this->map(Ids::ELEMENT_CONSTRUCTOR, fn(Reader $in) => Blocks::ELEMENT_CONSTRUCTOR()
|
||||
->setFacing(Facing::opposite($in->readLegacyHorizontalFacing()))
|
||||
);
|
||||
$this->mapStairs(Ids::END_BRICK_STAIRS, fn() => Blocks::END_STONE_BRICK_STAIRS());
|
||||
$this->map(Ids::END_STONE_BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::END_STONE_BRICK_WALL(), $in));
|
||||
$this->map(Ids::END_PORTAL_FRAME, function(Reader $in) : Block{
|
||||
return Blocks::END_PORTAL_FRAME()
|
||||
->setEye($in->readBool(StateNames::END_PORTAL_EYE_BIT))
|
||||
@ -1174,14 +1263,24 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
return Blocks::END_ROD()
|
||||
->setFacing($in->readEndRodFacingDirection());
|
||||
});
|
||||
$this->mapSlab(Ids::END_STONE_BRICK_SLAB, Ids::END_STONE_BRICK_DOUBLE_SLAB, fn() => Blocks::END_STONE_BRICK_SLAB());
|
||||
$this->map(Ids::ENDER_CHEST, function(Reader $in) : Block{
|
||||
return Blocks::ENDER_CHEST()
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::EXPOSED_COPPER, fn() => Helper::decodeCopper(Blocks::COPPER(), CopperOxidation::EXPOSED));
|
||||
$this->map(Ids::EXPOSED_CHISELED_COPPER, fn() => Helper::decodeCopper(Blocks::CHISELED_COPPER(), CopperOxidation::EXPOSED));
|
||||
$this->map(Ids::EXPOSED_COPPER_GRATE, fn() => Helper::decodeCopper(Blocks::COPPER_GRATE(), CopperOxidation::EXPOSED));
|
||||
$this->map(Ids::EXPOSED_CUT_COPPER, fn() => Helper::decodeCopper(Blocks::CUT_COPPER(), CopperOxidation::EXPOSED));
|
||||
$this->mapSlab(Ids::EXPOSED_CUT_COPPER_SLAB, Ids::EXPOSED_DOUBLE_CUT_COPPER_SLAB, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_SLAB(), CopperOxidation::EXPOSED));
|
||||
$this->mapStairs(Ids::EXPOSED_CUT_COPPER_STAIRS, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_STAIRS(), CopperOxidation::EXPOSED));
|
||||
$this->map(Ids::EXPOSED_COPPER_BULB, function(Reader $in) : Block{
|
||||
return Helper::decodeCopper(Blocks::COPPER_BULB(), CopperOxidation::EXPOSED)
|
||||
->setLit($in->readBool(StateNames::LIT))
|
||||
->setPowered($in->readBool(StateNames::POWERED_BIT));
|
||||
});
|
||||
$this->map(Ids::EXPOSED_COPPER_DOOR, fn(Reader $in) => Helper::decodeDoor(Helper::decodeCopper(Blocks::COPPER_DOOR(), CopperOxidation::EXPOSED), $in));
|
||||
$this->map(Ids::EXPOSED_COPPER_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Helper::decodeCopper(Blocks::COPPER_TRAPDOOR(), CopperOxidation::EXPOSED), $in));
|
||||
$this->map(Ids::FARMLAND, function(Reader $in) : Block{
|
||||
return Blocks::FARMLAND()
|
||||
->setWetness($in->readBoundedInt(StateNames::MOISTURIZED_AMOUNT, 0, 7));
|
||||
@ -1213,7 +1312,9 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
->setPowered($in->readBool(StateNames::RAIL_DATA_BIT))
|
||||
->setShape($in->readBoundedInt(StateNames::RAIL_DIRECTION, 0, 5));
|
||||
});
|
||||
$this->mapSlab(Ids::GRANITE_SLAB, Ids::GRANITE_DOUBLE_SLAB, fn() => Blocks::GRANITE_SLAB());
|
||||
$this->mapStairs(Ids::GRANITE_STAIRS, fn() => Blocks::GRANITE_STAIRS());
|
||||
$this->map(Ids::GRANITE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::GRANITE_WALL(), $in));
|
||||
$this->map(Ids::HAY_BLOCK, function(Reader $in) : Block{
|
||||
$in->ignored(StateNames::DEPRECATED);
|
||||
return Blocks::HAY_BALE()->setAxis($in->readPillarAxis());
|
||||
@ -1226,6 +1327,9 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
$this->map(Ids::IRON_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::IRON_DOOR(), $in));
|
||||
$this->map(Ids::IRON_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::IRON_TRAPDOOR(), $in));
|
||||
$this->map(Ids::LAB_TABLE, fn(Reader $in) => Blocks::LAB_TABLE()
|
||||
->setFacing(Facing::opposite($in->readLegacyHorizontalFacing()))
|
||||
);
|
||||
$this->map(Ids::LADDER, function(Reader $in) : Block{
|
||||
return Blocks::LADDER()
|
||||
->setFacing($in->readHorizontalFacing());
|
||||
@ -1260,10 +1364,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
default => throw $in->badValueException(StateNames::LEVER_DIRECTION, $value),
|
||||
});
|
||||
});
|
||||
$this->map(Ids::LIGHT_BLOCK, function(Reader $in) : Block{
|
||||
return Blocks::LIGHT()
|
||||
->setLightLevel($in->readBoundedInt(StateNames::BLOCK_LIGHT_LEVEL, Light::MIN_LIGHT_LEVEL, Light::MAX_LIGHT_LEVEL));
|
||||
});
|
||||
$this->map(Ids::LIGHTNING_ROD, function(Reader $in) : Block{
|
||||
return Blocks::LIGHTNING_ROD()
|
||||
->setFacing($in->readFacingDirection());
|
||||
@ -1301,25 +1401,21 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
return Blocks::LOOM()
|
||||
->setFacing($in->readLegacyHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::MATERIAL_REDUCER, fn(Reader $in) => Blocks::MATERIAL_REDUCER()
|
||||
->setFacing(Facing::opposite($in->readLegacyHorizontalFacing()))
|
||||
);
|
||||
$this->map(Ids::MEDIUM_AMETHYST_BUD, function(Reader $in) : Block{
|
||||
return Blocks::AMETHYST_CLUSTER()
|
||||
->setStage(AmethystCluster::STAGE_MEDIUM_BUD)
|
||||
->setFacing($in->readBlockFace());
|
||||
});
|
||||
$this->map(Ids::MELON_STEM, fn(Reader $in) => Helper::decodeStem(Blocks::MELON_STEM(), $in));
|
||||
$this->map(Ids::MONSTER_EGG, function(Reader $in) : Block{
|
||||
return match($type = $in->readString(StateNames::MONSTER_EGG_STONE_TYPE)){
|
||||
StringValues::MONSTER_EGG_STONE_TYPE_CHISELED_STONE_BRICK => Blocks::INFESTED_CHISELED_STONE_BRICK(),
|
||||
StringValues::MONSTER_EGG_STONE_TYPE_COBBLESTONE => Blocks::INFESTED_COBBLESTONE(),
|
||||
StringValues::MONSTER_EGG_STONE_TYPE_CRACKED_STONE_BRICK => Blocks::INFESTED_CRACKED_STONE_BRICK(),
|
||||
StringValues::MONSTER_EGG_STONE_TYPE_MOSSY_STONE_BRICK => Blocks::INFESTED_MOSSY_STONE_BRICK(),
|
||||
StringValues::MONSTER_EGG_STONE_TYPE_STONE => Blocks::INFESTED_STONE(),
|
||||
StringValues::MONSTER_EGG_STONE_TYPE_STONE_BRICK => Blocks::INFESTED_STONE_BRICK(),
|
||||
default => throw $in->badValueException(StateNames::MONSTER_EGG_STONE_TYPE, $type),
|
||||
};
|
||||
});
|
||||
$this->mapSlab(Ids::MOSSY_COBBLESTONE_SLAB, Ids::MOSSY_COBBLESTONE_DOUBLE_SLAB, fn() => Blocks::MOSSY_COBBLESTONE_SLAB());
|
||||
$this->mapStairs(Ids::MOSSY_COBBLESTONE_STAIRS, fn() => Blocks::MOSSY_COBBLESTONE_STAIRS());
|
||||
$this->map(Ids::MOSSY_COBBLESTONE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::MOSSY_COBBLESTONE_WALL(), $in));
|
||||
$this->mapSlab(Ids::MOSSY_STONE_BRICK_SLAB, Ids::MOSSY_STONE_BRICK_DOUBLE_SLAB, fn() => Blocks::MOSSY_STONE_BRICK_SLAB());
|
||||
$this->mapStairs(Ids::MOSSY_STONE_BRICK_STAIRS, fn() => Blocks::MOSSY_STONE_BRICK_STAIRS());
|
||||
$this->map(Ids::MOSSY_STONE_BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::MOSSY_STONE_BRICK_WALL(), $in));
|
||||
$this->mapSlab(Ids::MUD_BRICK_SLAB, Ids::MUD_BRICK_DOUBLE_SLAB, fn() => Blocks::MUD_BRICK_SLAB());
|
||||
$this->mapStairs(Ids::MUD_BRICK_STAIRS, fn() => Blocks::MUD_BRICK_STAIRS());
|
||||
$this->map(Ids::MUD_BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::MUD_BRICK_WALL(), $in));
|
||||
@ -1327,18 +1423,31 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
return Blocks::MUDDY_MANGROVE_ROOTS()
|
||||
->setAxis($in->readPillarAxis());
|
||||
});
|
||||
$this->mapSlab(Ids::NETHER_BRICK_SLAB, Ids::NETHER_BRICK_DOUBLE_SLAB, fn() => Blocks::NETHER_BRICK_SLAB());
|
||||
$this->mapStairs(Ids::NETHER_BRICK_STAIRS, fn() => Blocks::NETHER_BRICK_STAIRS());
|
||||
$this->map(Ids::NETHER_BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::NETHER_BRICK_WALL(), $in));
|
||||
$this->map(Ids::NETHER_WART, function(Reader $in) : Block{
|
||||
return Blocks::NETHER_WART()
|
||||
->setAge($in->readBoundedInt(StateNames::AGE, 0, 3));
|
||||
});
|
||||
$this->mapSlab(Ids::NORMAL_STONE_SLAB, Ids::NORMAL_STONE_DOUBLE_SLAB, fn() => Blocks::STONE_SLAB());
|
||||
$this->mapStairs(Ids::NORMAL_STONE_STAIRS, fn() => Blocks::STONE_STAIRS());
|
||||
$this->map(Ids::OCHRE_FROGLIGHT, fn(Reader $in) => Blocks::FROGLIGHT()->setFroglightType(FroglightType::OCHRE)->setAxis($in->readPillarAxis()));
|
||||
$this->map(Ids::OXIDIZED_COPPER, fn() => Helper::decodeCopper(Blocks::COPPER(), CopperOxidation::OXIDIZED));
|
||||
$this->map(Ids::OXIDIZED_CHISELED_COPPER, fn() => Helper::decodeCopper(Blocks::CHISELED_COPPER(), CopperOxidation::OXIDIZED));
|
||||
$this->map(Ids::OXIDIZED_COPPER_GRATE, fn() => Helper::decodeCopper(Blocks::COPPER_GRATE(), CopperOxidation::OXIDIZED));
|
||||
$this->map(Ids::OXIDIZED_CUT_COPPER, fn() => Helper::decodeCopper(Blocks::CUT_COPPER(), CopperOxidation::OXIDIZED));
|
||||
$this->mapSlab(Ids::OXIDIZED_CUT_COPPER_SLAB, Ids::OXIDIZED_DOUBLE_CUT_COPPER_SLAB, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_SLAB(), CopperOxidation::OXIDIZED));
|
||||
$this->mapStairs(Ids::OXIDIZED_CUT_COPPER_STAIRS, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_STAIRS(), CopperOxidation::OXIDIZED));
|
||||
$this->map(Ids::OXIDIZED_COPPER_BULB, function(Reader $in) : Block{
|
||||
return Helper::decodeCopper(Blocks::COPPER_BULB(), CopperOxidation::OXIDIZED)
|
||||
->setLit($in->readBool(StateNames::LIT))
|
||||
->setPowered($in->readBool(StateNames::POWERED_BIT));
|
||||
});
|
||||
$this->map(Ids::OXIDIZED_COPPER_DOOR, fn(Reader $in) => Helper::decodeDoor(Helper::decodeCopper(Blocks::COPPER_DOOR(), CopperOxidation::OXIDIZED), $in));
|
||||
$this->map(Ids::OXIDIZED_COPPER_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Helper::decodeCopper(Blocks::COPPER_TRAPDOOR(), CopperOxidation::OXIDIZED), $in));
|
||||
$this->map(Ids::PEARLESCENT_FROGLIGHT, fn(Reader $in) => Blocks::FROGLIGHT()->setFroglightType(FroglightType::PEARLESCENT)->setAxis($in->readPillarAxis()));
|
||||
$this->mapSlab(Ids::PETRIFIED_OAK_SLAB, Ids::PETRIFIED_OAK_DOUBLE_SLAB, fn() => Blocks::FAKE_WOODEN_SLAB());
|
||||
$this->map(Ids::PINK_PETALS, function(Reader $in) : Block{
|
||||
//Pink petals only uses 0-3, but GROWTH state can go up to 7
|
||||
$growth = $in->readBoundedInt(StateNames::GROWTH, 0, 7);
|
||||
@ -1362,6 +1471,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
return Blocks::PITCHER_PLANT()
|
||||
->setTop($in->readBool(StateNames::UPPER_BLOCK_BIT));
|
||||
});
|
||||
$this->mapSlab(Ids::POLISHED_ANDESITE_SLAB, Ids::POLISHED_ANDESITE_DOUBLE_SLAB, fn() => Blocks::POLISHED_ANDESITE_SLAB());
|
||||
$this->mapStairs(Ids::POLISHED_ANDESITE_STAIRS, fn() => Blocks::POLISHED_ANDESITE_STAIRS());
|
||||
$this->map(Ids::POLISHED_BASALT, function(Reader $in) : Block{
|
||||
return Blocks::POLISHED_BASALT()
|
||||
@ -1378,8 +1488,13 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->mapSlab(Ids::POLISHED_DEEPSLATE_SLAB, Ids::POLISHED_DEEPSLATE_DOUBLE_SLAB, fn() => Blocks::POLISHED_DEEPSLATE_SLAB());
|
||||
$this->mapStairs(Ids::POLISHED_DEEPSLATE_STAIRS, fn() => Blocks::POLISHED_DEEPSLATE_STAIRS());
|
||||
$this->map(Ids::POLISHED_DEEPSLATE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::POLISHED_DEEPSLATE_WALL(), $in));
|
||||
$this->mapSlab(Ids::POLISHED_DIORITE_SLAB, Ids::POLISHED_DIORITE_DOUBLE_SLAB, fn() => Blocks::POLISHED_DIORITE_SLAB());
|
||||
$this->mapStairs(Ids::POLISHED_DIORITE_STAIRS, fn() => Blocks::POLISHED_DIORITE_STAIRS());
|
||||
$this->mapSlab(Ids::POLISHED_GRANITE_SLAB, Ids::POLISHED_GRANITE_DOUBLE_SLAB, fn() => Blocks::POLISHED_GRANITE_SLAB());
|
||||
$this->mapStairs(Ids::POLISHED_GRANITE_STAIRS, fn() => Blocks::POLISHED_GRANITE_STAIRS());
|
||||
$this->mapSlab(Ids::POLISHED_TUFF_SLAB, Ids::POLISHED_TUFF_DOUBLE_SLAB, fn() => Blocks::POLISHED_TUFF_SLAB());
|
||||
$this->mapStairs(Ids::POLISHED_TUFF_STAIRS, fn() => Blocks::POLISHED_TUFF_STAIRS());
|
||||
$this->map(Ids::POLISHED_TUFF_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::POLISHED_TUFF_WALL(), $in));
|
||||
$this->map(Ids::PORTAL, function(Reader $in) : Block{
|
||||
return Blocks::NETHER_PORTAL()
|
||||
->setAxis(match($value = $in->readString(StateNames::PORTAL_AXIS)){
|
||||
@ -1393,15 +1508,10 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::POWERED_COMPARATOR, fn(Reader $in) => Helper::decodeComparator(Blocks::REDSTONE_COMPARATOR(), $in));
|
||||
$this->map(Ids::POWERED_REPEATER, fn(Reader $in) => Helper::decodeRepeater(Blocks::REDSTONE_REPEATER(), $in)
|
||||
->setPowered(true));
|
||||
$this->map(Ids::PRISMARINE, function(Reader $in) : Block{
|
||||
return match($type = $in->readString(StateNames::PRISMARINE_BLOCK_TYPE)){
|
||||
StringValues::PRISMARINE_BLOCK_TYPE_BRICKS => Blocks::PRISMARINE_BRICKS(),
|
||||
StringValues::PRISMARINE_BLOCK_TYPE_DARK => Blocks::DARK_PRISMARINE(),
|
||||
StringValues::PRISMARINE_BLOCK_TYPE_DEFAULT => Blocks::PRISMARINE(),
|
||||
default => throw $in->badValueException(StateNames::PRISMARINE_BLOCK_TYPE, $type),
|
||||
};
|
||||
});
|
||||
$this->mapSlab(Ids::PRISMARINE_BRICK_SLAB, Ids::PRISMARINE_BRICK_DOUBLE_SLAB, fn() => Blocks::PRISMARINE_BRICKS_SLAB());
|
||||
$this->mapStairs(Ids::PRISMARINE_BRICKS_STAIRS, fn() => Blocks::PRISMARINE_BRICKS_STAIRS());
|
||||
$this->map(Ids::PRISMARINE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::PRISMARINE_WALL(), $in));
|
||||
$this->mapSlab(Ids::PRISMARINE_SLAB, Ids::PRISMARINE_DOUBLE_SLAB, fn() => Blocks::PRISMARINE_SLAB());
|
||||
$this->mapStairs(Ids::PRISMARINE_STAIRS, fn() => Blocks::PRISMARINE_STAIRS());
|
||||
$this->map(Ids::PUMPKIN, function(Reader $in) : Block{
|
||||
$in->ignored(StateNames::MC_CARDINAL_DIRECTION); //obsolete
|
||||
@ -1409,53 +1519,33 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
$this->map(Ids::PUMPKIN_STEM, fn(Reader $in) => Helper::decodeStem(Blocks::PUMPKIN_STEM(), $in));
|
||||
$this->map(Ids::PURPUR_BLOCK, function(Reader $in) : Block{
|
||||
$type = $in->readString(StateNames::CHISEL_TYPE);
|
||||
if($type === StringValues::CHISEL_TYPE_LINES){
|
||||
return Blocks::PURPUR_PILLAR()->setAxis($in->readPillarAxis());
|
||||
}else{
|
||||
$in->ignored(StateNames::PILLAR_AXIS); //axis only applies to pillars
|
||||
return match($type){
|
||||
StringValues::CHISEL_TYPE_CHISELED, //TODO: bug in MCPE
|
||||
StringValues::CHISEL_TYPE_SMOOTH, //TODO: bug in MCPE
|
||||
StringValues::CHISEL_TYPE_DEFAULT => Blocks::PURPUR(),
|
||||
default => throw $in->badValueException(StateNames::CHISEL_TYPE, $type),
|
||||
};
|
||||
}
|
||||
$in->ignored(StateNames::PILLAR_AXIS); //???
|
||||
return Blocks::PURPUR();
|
||||
});
|
||||
$this->map(Ids::PURPUR_PILLAR, fn(Reader $in) => Blocks::PURPUR_PILLAR()->setAxis($in->readPillarAxis()));
|
||||
$this->mapSlab(Ids::PURPUR_SLAB, Ids::PURPUR_DOUBLE_SLAB, fn() => Blocks::PURPUR_SLAB());
|
||||
$this->mapStairs(Ids::PURPUR_STAIRS, fn() => Blocks::PURPUR_STAIRS());
|
||||
$this->map(Ids::QUARTZ_BLOCK, function(Reader $in) : Block{
|
||||
switch($type = $in->readString(StateNames::CHISEL_TYPE)){
|
||||
case StringValues::CHISEL_TYPE_CHISELED:
|
||||
return Blocks::CHISELED_QUARTZ()->setAxis($in->readPillarAxis());
|
||||
case StringValues::CHISEL_TYPE_DEFAULT:
|
||||
$in->ignored(StateNames::PILLAR_AXIS);
|
||||
return Blocks::QUARTZ();
|
||||
case StringValues::CHISEL_TYPE_LINES:
|
||||
return Blocks::QUARTZ_PILLAR()->setAxis($in->readPillarAxis());
|
||||
case StringValues::CHISEL_TYPE_SMOOTH:
|
||||
$in->ignored(StateNames::PILLAR_AXIS);
|
||||
return Blocks::SMOOTH_QUARTZ();
|
||||
default:
|
||||
throw $in->badValueException(StateNames::CHISEL_TYPE, $type);
|
||||
}
|
||||
$this->map(Ids::QUARTZ_BLOCK, function(Reader $in) : Opaque{
|
||||
$in->ignored(StateNames::PILLAR_AXIS);
|
||||
return Blocks::QUARTZ();
|
||||
});
|
||||
$this->map(Ids::QUARTZ_PILLAR, function(Reader $in) : Block{
|
||||
return Blocks::QUARTZ_PILLAR()
|
||||
->setAxis($in->readPillarAxis());
|
||||
});
|
||||
$this->mapSlab(Ids::QUARTZ_SLAB, Ids::QUARTZ_DOUBLE_SLAB, fn() => Blocks::QUARTZ_SLAB());
|
||||
$this->mapStairs(Ids::QUARTZ_STAIRS, fn() => Blocks::QUARTZ_STAIRS());
|
||||
$this->map(Ids::RAIL, function(Reader $in) : Block{
|
||||
return Blocks::RAIL()
|
||||
->setShape($in->readBoundedInt(StateNames::RAIL_DIRECTION, 0, 9));
|
||||
});
|
||||
$this->map(Ids::RED_MUSHROOM_BLOCK, fn(Reader $in) => Helper::decodeMushroomBlock(Blocks::RED_MUSHROOM_BLOCK(), $in));
|
||||
$this->mapSlab(Ids::RED_NETHER_BRICK_SLAB, Ids::RED_NETHER_BRICK_DOUBLE_SLAB, fn() => Blocks::RED_NETHER_BRICK_SLAB());
|
||||
$this->mapStairs(Ids::RED_NETHER_BRICK_STAIRS, fn() => Blocks::RED_NETHER_BRICK_STAIRS());
|
||||
$this->map(Ids::RED_SANDSTONE, function(Reader $in) : Block{
|
||||
return match($type = $in->readString(StateNames::SAND_STONE_TYPE)){
|
||||
StringValues::SAND_STONE_TYPE_CUT => Blocks::CUT_RED_SANDSTONE(),
|
||||
StringValues::SAND_STONE_TYPE_DEFAULT => Blocks::RED_SANDSTONE(),
|
||||
StringValues::SAND_STONE_TYPE_HEIROGLYPHS => Blocks::CHISELED_RED_SANDSTONE(),
|
||||
StringValues::SAND_STONE_TYPE_SMOOTH => Blocks::SMOOTH_RED_SANDSTONE(),
|
||||
default => throw $in->badValueException(StateNames::SAND_STONE_TYPE, $type),
|
||||
};
|
||||
});
|
||||
$this->map(Ids::RED_NETHER_BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::RED_NETHER_BRICK_WALL(), $in));
|
||||
$this->mapSlab(Ids::RED_SANDSTONE_SLAB, Ids::RED_SANDSTONE_DOUBLE_SLAB, fn() => Blocks::RED_SANDSTONE_SLAB());
|
||||
$this->mapStairs(Ids::RED_SANDSTONE_STAIRS, fn() => Blocks::RED_SANDSTONE_STAIRS());
|
||||
$this->map(Ids::RED_SANDSTONE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::RED_SANDSTONE_WALL(), $in));
|
||||
$this->map(Ids::REDSTONE_LAMP, function() : Block{
|
||||
return Blocks::REDSTONE_LAMP()
|
||||
->setPowered(false);
|
||||
@ -1477,32 +1567,14 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
return Blocks::SUGARCANE()
|
||||
->setAge($in->readBoundedInt(StateNames::AGE, 0, 15));
|
||||
});
|
||||
$this->map(Ids::SAND, function(Reader $in) : Block{
|
||||
return match($value = $in->readString(StateNames::SAND_TYPE)){
|
||||
StringValues::SAND_TYPE_NORMAL => Blocks::SAND(),
|
||||
StringValues::SAND_TYPE_RED => Blocks::RED_SAND(),
|
||||
default => throw $in->badValueException(StateNames::SAND_TYPE, $value),
|
||||
};
|
||||
});
|
||||
$this->map(Ids::SANDSTONE, function(Reader $in) : Block{
|
||||
return match($type = $in->readString(StateNames::SAND_STONE_TYPE)){
|
||||
StringValues::SAND_STONE_TYPE_CUT => Blocks::CUT_SANDSTONE(),
|
||||
StringValues::SAND_STONE_TYPE_DEFAULT => Blocks::SANDSTONE(),
|
||||
StringValues::SAND_STONE_TYPE_HEIROGLYPHS => Blocks::CHISELED_SANDSTONE(),
|
||||
StringValues::SAND_STONE_TYPE_SMOOTH => Blocks::SMOOTH_SANDSTONE(),
|
||||
default => throw $in->badValueException(StateNames::SAND_STONE_TYPE, $type),
|
||||
};
|
||||
});
|
||||
$this->mapSlab(Ids::SANDSTONE_SLAB, Ids::SANDSTONE_DOUBLE_SLAB, fn() => Blocks::SANDSTONE_SLAB());
|
||||
$this->mapStairs(Ids::SANDSTONE_STAIRS, fn() => Blocks::SANDSTONE_STAIRS());
|
||||
$this->map(Ids::SANDSTONE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::SANDSTONE_WALL(), $in));
|
||||
$this->map(Ids::SEA_PICKLE, function(Reader $in) : Block{
|
||||
return Blocks::SEA_PICKLE()
|
||||
->setCount($in->readBoundedInt(StateNames::CLUSTER_COUNT, 0, 3) + 1)
|
||||
->setUnderwater(!$in->readBool(StateNames::DEAD_BIT));
|
||||
});
|
||||
$this->map(Ids::SKULL, function(Reader $in) : Block{
|
||||
return Blocks::MOB_HEAD()
|
||||
->setFacing($in->readFacingWithoutDown());
|
||||
});
|
||||
$this->map(Ids::SMOKER, function(Reader $in) : Block{
|
||||
return Blocks::SMOKER()
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
@ -1518,13 +1590,26 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setTop($in->readBool(StateNames::UPPER_BLOCK_BIT));
|
||||
});
|
||||
$this->map(Ids::SMOOTH_QUARTZ, function(Reader $in) : Block{
|
||||
$in->ignored(StateNames::PILLAR_AXIS);
|
||||
return Blocks::SMOOTH_QUARTZ();
|
||||
});
|
||||
$this->mapSlab(Ids::SMOOTH_QUARTZ_SLAB, Ids::SMOOTH_QUARTZ_DOUBLE_SLAB, fn() => Blocks::SMOOTH_QUARTZ_SLAB());
|
||||
$this->mapStairs(Ids::SMOOTH_QUARTZ_STAIRS, fn() => Blocks::SMOOTH_QUARTZ_STAIRS());
|
||||
$this->mapSlab(Ids::SMOOTH_RED_SANDSTONE_SLAB, Ids::SMOOTH_RED_SANDSTONE_DOUBLE_SLAB, fn() => Blocks::SMOOTH_RED_SANDSTONE_SLAB());
|
||||
$this->mapStairs(Ids::SMOOTH_RED_SANDSTONE_STAIRS, fn() => Blocks::SMOOTH_RED_SANDSTONE_STAIRS());
|
||||
$this->mapSlab(Ids::SMOOTH_SANDSTONE_SLAB, Ids::SMOOTH_SANDSTONE_DOUBLE_SLAB, fn() => Blocks::SMOOTH_SANDSTONE_SLAB());
|
||||
$this->mapStairs(Ids::SMOOTH_SANDSTONE_STAIRS, fn() => Blocks::SMOOTH_SANDSTONE_STAIRS());
|
||||
$this->mapSlab(Ids::SMOOTH_STONE_SLAB, Ids::SMOOTH_STONE_DOUBLE_SLAB, fn() => Blocks::SMOOTH_STONE_SLAB());
|
||||
$this->map(Ids::SNOW_LAYER, function(Reader $in) : Block{
|
||||
$in->ignored(StateNames::COVERED_BIT); //seems to be useless
|
||||
return Blocks::SNOW_LAYER()->setLayers($in->readBoundedInt(StateNames::HEIGHT, 0, 7) + 1);
|
||||
});
|
||||
$this->map(Ids::SOUL_CAMPFIRE, function(Reader $in) : Block{
|
||||
return Blocks::SOUL_CAMPFIRE()
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setLit(!$in->readBool(StateNames::EXTINGUISHED));
|
||||
});
|
||||
$this->map(Ids::SOUL_FIRE, function(Reader $in) : Block{
|
||||
$in->ignored(StateNames::AGE); //this is useless for soul fire, since it doesn't have the logic associated
|
||||
return Blocks::SOUL_FIRE();
|
||||
@ -1537,46 +1622,16 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
return Blocks::SOUL_TORCH()
|
||||
->setFacing($in->readTorchFacing());
|
||||
});
|
||||
$this->map(Ids::SPONGE, function(Reader $in) : Block{
|
||||
return Blocks::SPONGE()->setWet(match($type = $in->readString(StateNames::SPONGE_TYPE)){
|
||||
StringValues::SPONGE_TYPE_DRY => false,
|
||||
StringValues::SPONGE_TYPE_WET => true,
|
||||
default => throw $in->badValueException(StateNames::SPONGE_TYPE, $type),
|
||||
});
|
||||
});
|
||||
$this->map(Ids::STANDING_BANNER, function(Reader $in) : Block{
|
||||
return Blocks::BANNER()
|
||||
->setRotation($in->readBoundedInt(StateNames::GROUND_SIGN_DIRECTION, 0, 15));
|
||||
});
|
||||
$this->mapSlab(Ids::STONE_BRICK_SLAB, Ids::STONE_BRICK_DOUBLE_SLAB, fn() => Blocks::STONE_BRICK_SLAB());
|
||||
$this->mapStairs(Ids::STONE_BRICK_STAIRS, fn() => Blocks::STONE_BRICK_STAIRS());
|
||||
$this->map(Ids::STONE_BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::STONE_BRICK_WALL(), $in));
|
||||
$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));
|
||||
|
||||
//mess for partially flattened slabs - the single IDs were flattened but not the double ones
|
||||
$this->map(Ids::DOUBLE_STONE_BLOCK_SLAB, fn(Reader $in) => Helper::decodeDoubleSlab(Helper::mapStoneSlab1Type($in), $in));
|
||||
$this->map(Ids::BRICK_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::BRICK_SLAB(), $in));
|
||||
$this->map(Ids::COBBLESTONE_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::COBBLESTONE_SLAB(), $in));
|
||||
$this->map(Ids::NETHER_BRICK_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::NETHER_BRICK_SLAB(), $in));
|
||||
$this->map(Ids::PETRIFIED_OAK_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::FAKE_WOODEN_SLAB(), $in));
|
||||
$this->map(Ids::QUARTZ_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::QUARTZ_SLAB(), $in));
|
||||
$this->map(Ids::SANDSTONE_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::SANDSTONE_SLAB(), $in));
|
||||
$this->map(Ids::SMOOTH_STONE_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::SMOOTH_STONE_SLAB(), $in));
|
||||
$this->map(Ids::STONE_BRICK_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::STONE_BRICK_SLAB(), $in));
|
||||
|
||||
$this->mapSlab(Ids::STONE_BLOCK_SLAB2, Ids::DOUBLE_STONE_BLOCK_SLAB2, fn(Reader $in) => Helper::mapStoneSlab2Type($in));
|
||||
$this->mapSlab(Ids::STONE_BLOCK_SLAB3, Ids::DOUBLE_STONE_BLOCK_SLAB3, fn(Reader $in) => Helper::mapStoneSlab3Type($in));
|
||||
$this->mapSlab(Ids::STONE_BLOCK_SLAB4, Ids::DOUBLE_STONE_BLOCK_SLAB4, fn(Reader $in) => Helper::mapStoneSlab4Type($in));
|
||||
$this->mapStairs(Ids::STONE_STAIRS, fn() => Blocks::COBBLESTONE_STAIRS());
|
||||
$this->map(Ids::STONEBRICK, function(Reader $in) : Block{
|
||||
return match($type = $in->readString(StateNames::STONE_BRICK_TYPE)){
|
||||
StringValues::STONE_BRICK_TYPE_SMOOTH, //TODO: bug in vanilla
|
||||
StringValues::STONE_BRICK_TYPE_DEFAULT => Blocks::STONE_BRICKS(),
|
||||
StringValues::STONE_BRICK_TYPE_CHISELED => Blocks::CHISELED_STONE_BRICKS(),
|
||||
StringValues::STONE_BRICK_TYPE_CRACKED => Blocks::CRACKED_STONE_BRICKS(),
|
||||
StringValues::STONE_BRICK_TYPE_MOSSY => Blocks::MOSSY_STONE_BRICKS(),
|
||||
default => throw $in->badValueException(StateNames::STONE_BRICK_TYPE, $type),
|
||||
};
|
||||
});
|
||||
$this->map(Ids::STONECUTTER_BLOCK, function(Reader $in) : Block{
|
||||
return Blocks::STONECUTTER()
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
@ -1590,7 +1645,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::TNT, function(Reader $in) : Block{
|
||||
return Blocks::TNT()
|
||||
->setUnstable($in->readBool(StateNames::EXPLODE_BIT))
|
||||
->setWorksUnderwater($in->readBool(StateNames::ALLOW_UNDERWATER_BIT));
|
||||
->setWorksUnderwater(false);
|
||||
});
|
||||
$this->map(Ids::TORCH, function(Reader $in) : Block{
|
||||
return Blocks::TORCH()
|
||||
@ -1618,10 +1673,21 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
->setFacing($in->readLegacyHorizontalFacing())
|
||||
->setPowered($in->readBool(StateNames::POWERED_BIT));
|
||||
});
|
||||
$this->mapSlab(Ids::TUFF_BRICK_SLAB, Ids::TUFF_BRICK_DOUBLE_SLAB, fn() => Blocks::TUFF_BRICK_SLAB());
|
||||
$this->mapStairs(Ids::TUFF_BRICK_STAIRS, fn() => Blocks::TUFF_BRICK_STAIRS());
|
||||
$this->map(Ids::TUFF_BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::TUFF_BRICK_WALL(), $in));
|
||||
$this->mapSlab(Ids::TUFF_SLAB, Ids::TUFF_DOUBLE_SLAB, fn() => Blocks::TUFF_SLAB());
|
||||
$this->mapStairs(Ids::TUFF_STAIRS, fn() => Blocks::TUFF_STAIRS());
|
||||
$this->map(Ids::TUFF_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::TUFF_WALL(), $in));
|
||||
$this->map(Ids::TWISTING_VINES, function(Reader $in) : Block{
|
||||
return Blocks::TWISTING_VINES()
|
||||
->setAge($in->readBoundedInt(StateNames::TWISTING_VINES_AGE, 0, 25));
|
||||
});
|
||||
$this->map(Ids::UNDERWATER_TNT, function(Reader $in) : Block{
|
||||
return Blocks::TNT()
|
||||
->setUnstable($in->readBool(StateNames::EXPLODE_BIT))
|
||||
->setWorksUnderwater(true);
|
||||
});
|
||||
$this->map(Ids::UNDERWATER_TORCH, function(Reader $in) : Block{
|
||||
return Blocks::UNDERWATER_TORCH()
|
||||
->setFacing($in->readTorchFacing());
|
||||
@ -1649,25 +1715,70 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
$this->map(Ids::WATER, fn(Reader $in) => Helper::decodeStillLiquid(Blocks::WATER(), $in));
|
||||
$this->map(Ids::WAXED_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::COPPER(), CopperOxidation::NONE));
|
||||
$this->map(Ids::WAXED_CHISELED_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::CHISELED_COPPER(), CopperOxidation::NONE));
|
||||
$this->map(Ids::WAXED_COPPER_GRATE, fn() => Helper::decodeWaxedCopper(Blocks::COPPER_GRATE(), CopperOxidation::NONE));
|
||||
$this->map(Ids::WAXED_CUT_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER(), CopperOxidation::NONE));
|
||||
$this->mapSlab(Ids::WAXED_CUT_COPPER_SLAB, Ids::WAXED_DOUBLE_CUT_COPPER_SLAB, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER_SLAB(), CopperOxidation::NONE));
|
||||
$this->mapStairs(Ids::WAXED_CUT_COPPER_STAIRS, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER_STAIRS(), CopperOxidation::NONE));
|
||||
$this->map(Ids::WAXED_COPPER_BULB, function(Reader $in) : Block{
|
||||
return Helper::decodeWaxedCopper(Blocks::COPPER_BULB(), CopperOxidation::NONE)
|
||||
->setLit($in->readBool(StateNames::LIT))
|
||||
->setPowered($in->readBool(StateNames::POWERED_BIT));
|
||||
});
|
||||
$this->map(Ids::WAXED_COPPER_DOOR, fn(Reader $in) => Helper::decodeDoor(Helper::decodeWaxedCopper(Blocks::COPPER_DOOR(), CopperOxidation::NONE), $in));
|
||||
$this->map(Ids::WAXED_COPPER_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Helper::decodeWaxedCopper(Blocks::COPPER_TRAPDOOR(), CopperOxidation::NONE), $in));
|
||||
$this->map(Ids::WAXED_EXPOSED_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::COPPER(), CopperOxidation::EXPOSED));
|
||||
$this->map(Ids::WAXED_EXPOSED_CHISELED_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::CHISELED_COPPER(), CopperOxidation::EXPOSED));
|
||||
$this->map(Ids::WAXED_EXPOSED_COPPER_GRATE, fn() => Helper::decodeWaxedCopper(Blocks::COPPER_GRATE(), CopperOxidation::EXPOSED));
|
||||
$this->map(Ids::WAXED_EXPOSED_CUT_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER(), CopperOxidation::EXPOSED));
|
||||
$this->mapSlab(Ids::WAXED_EXPOSED_CUT_COPPER_SLAB, Ids::WAXED_EXPOSED_DOUBLE_CUT_COPPER_SLAB, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER_SLAB(), CopperOxidation::EXPOSED));
|
||||
$this->mapStairs(Ids::WAXED_EXPOSED_CUT_COPPER_STAIRS, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER_STAIRS(), CopperOxidation::EXPOSED));
|
||||
$this->map(Ids::WAXED_EXPOSED_COPPER_BULB, function(Reader $in) : Block{
|
||||
return Helper::decodeWaxedCopper(Blocks::COPPER_BULB(), CopperOxidation::EXPOSED)
|
||||
->setLit($in->readBool(StateNames::LIT))
|
||||
->setPowered($in->readBool(StateNames::POWERED_BIT));
|
||||
});
|
||||
$this->map(Ids::WAXED_EXPOSED_COPPER_DOOR, fn(Reader $in) => Helper::decodeDoor(Helper::decodeWaxedCopper(Blocks::COPPER_DOOR(), CopperOxidation::EXPOSED), $in));
|
||||
$this->map(Ids::WAXED_EXPOSED_COPPER_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Helper::decodeWaxedCopper(Blocks::COPPER_TRAPDOOR(), CopperOxidation::EXPOSED), $in));
|
||||
$this->map(Ids::WAXED_OXIDIZED_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::COPPER(), CopperOxidation::OXIDIZED));
|
||||
$this->map(Ids::WAXED_OXIDIZED_CHISELED_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::CHISELED_COPPER(), CopperOxidation::OXIDIZED));
|
||||
$this->map(Ids::WAXED_OXIDIZED_COPPER_GRATE, fn() => Helper::decodeWaxedCopper(Blocks::COPPER_GRATE(), CopperOxidation::OXIDIZED));
|
||||
$this->map(Ids::WAXED_OXIDIZED_CUT_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER(), CopperOxidation::OXIDIZED));
|
||||
$this->mapSlab(Ids::WAXED_OXIDIZED_CUT_COPPER_SLAB, Ids::WAXED_OXIDIZED_DOUBLE_CUT_COPPER_SLAB, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER_SLAB(), CopperOxidation::OXIDIZED));
|
||||
$this->mapStairs(Ids::WAXED_OXIDIZED_CUT_COPPER_STAIRS, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER_STAIRS(), CopperOxidation::OXIDIZED));
|
||||
$this->map(Ids::WAXED_OXIDIZED_COPPER_BULB, function(Reader $in) : Block{
|
||||
return Helper::decodeWaxedCopper(Blocks::COPPER_BULB(), CopperOxidation::OXIDIZED)
|
||||
->setLit($in->readBool(StateNames::LIT))
|
||||
->setPowered($in->readBool(StateNames::POWERED_BIT));
|
||||
});
|
||||
$this->map(Ids::WAXED_OXIDIZED_COPPER_DOOR, fn(Reader $in) => Helper::decodeDoor(Helper::decodeWaxedCopper(Blocks::COPPER_DOOR(), CopperOxidation::OXIDIZED), $in));
|
||||
$this->map(Ids::WAXED_OXIDIZED_COPPER_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Helper::decodeWaxedCopper(Blocks::COPPER_TRAPDOOR(), CopperOxidation::OXIDIZED), $in));
|
||||
$this->map(Ids::WAXED_WEATHERED_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::COPPER(), CopperOxidation::WEATHERED));
|
||||
$this->map(Ids::WAXED_WEATHERED_CHISELED_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::CHISELED_COPPER(), CopperOxidation::WEATHERED));
|
||||
$this->map(Ids::WAXED_WEATHERED_COPPER_GRATE, fn() => Helper::decodeWaxedCopper(Blocks::COPPER_GRATE(), CopperOxidation::WEATHERED));
|
||||
$this->map(Ids::WAXED_WEATHERED_CUT_COPPER, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER(), CopperOxidation::WEATHERED));
|
||||
$this->mapSlab(Ids::WAXED_WEATHERED_CUT_COPPER_SLAB, Ids::WAXED_WEATHERED_DOUBLE_CUT_COPPER_SLAB, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER_SLAB(), CopperOxidation::WEATHERED));
|
||||
$this->mapStairs(Ids::WAXED_WEATHERED_CUT_COPPER_STAIRS, fn() => Helper::decodeWaxedCopper(Blocks::CUT_COPPER_STAIRS(), CopperOxidation::WEATHERED));
|
||||
$this->map(Ids::WAXED_WEATHERED_COPPER_BULB, function(Reader $in) : Block{
|
||||
return Helper::decodeWaxedCopper(Blocks::COPPER_BULB(), CopperOxidation::WEATHERED)
|
||||
->setLit($in->readBool(StateNames::LIT))
|
||||
->setPowered($in->readBool(StateNames::POWERED_BIT));
|
||||
});
|
||||
$this->map(Ids::WAXED_WEATHERED_COPPER_DOOR, fn(Reader $in) => Helper::decodeDoor(Helper::decodeWaxedCopper(Blocks::COPPER_DOOR(), CopperOxidation::WEATHERED), $in));
|
||||
$this->map(Ids::WAXED_WEATHERED_COPPER_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Helper::decodeWaxedCopper(Blocks::COPPER_TRAPDOOR(), CopperOxidation::WEATHERED), $in));
|
||||
$this->map(Ids::WEATHERED_COPPER, fn() => Helper::decodeCopper(Blocks::COPPER(), CopperOxidation::WEATHERED));
|
||||
$this->map(Ids::WEATHERED_CHISELED_COPPER, fn() => Helper::decodeCopper(Blocks::CHISELED_COPPER(), CopperOxidation::WEATHERED));
|
||||
$this->map(Ids::WEATHERED_COPPER_GRATE, fn() => Helper::decodeCopper(Blocks::COPPER_GRATE(), CopperOxidation::WEATHERED));
|
||||
$this->map(Ids::WEATHERED_CUT_COPPER, fn() => Helper::decodeCopper(Blocks::CUT_COPPER(), CopperOxidation::WEATHERED));
|
||||
$this->mapSlab(Ids::WEATHERED_CUT_COPPER_SLAB, Ids::WEATHERED_DOUBLE_CUT_COPPER_SLAB, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_SLAB(), CopperOxidation::WEATHERED));
|
||||
$this->mapStairs(Ids::WEATHERED_CUT_COPPER_STAIRS, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_STAIRS(), CopperOxidation::WEATHERED));
|
||||
$this->map(Ids::WEATHERED_COPPER_BULB, function(Reader $in) : Block{
|
||||
return Helper::decodeCopper(Blocks::COPPER_BULB(), CopperOxidation::WEATHERED)
|
||||
->setLit($in->readBool(StateNames::LIT))
|
||||
->setPowered($in->readBool(StateNames::POWERED_BIT));
|
||||
});
|
||||
$this->map(Ids::WEATHERED_COPPER_DOOR, fn(Reader $in) => Helper::decodeDoor(Helper::decodeCopper(Blocks::COPPER_DOOR(), CopperOxidation::WEATHERED), $in));
|
||||
$this->map(Ids::WEATHERED_COPPER_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Helper::decodeCopper(Blocks::COPPER_TRAPDOOR(), CopperOxidation::WEATHERED), $in));
|
||||
$this->map(Ids::WEEPING_VINES, function(Reader $in) : Block{
|
||||
return Blocks::WEEPING_VINES()
|
||||
->setAge($in->readBoundedInt(StateNames::WEEPING_VINES_AGE, 0, 25));
|
||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\bedrock\block\upgrade;
|
||||
|
||||
use pocketmine\data\bedrock\block\upgrade\BlockStateUpgradeSchemaFlattenInfo as FlattenInfo;
|
||||
use pocketmine\data\bedrock\block\upgrade\BlockStateUpgradeSchemaValueRemap as ValueRemap;
|
||||
use pocketmine\nbt\tag\Tag;
|
||||
use function count;
|
||||
@ -58,6 +59,12 @@ final class BlockStateUpgradeSchema{
|
||||
*/
|
||||
public array $remappedPropertyValues = [];
|
||||
|
||||
/**
|
||||
* @var FlattenInfo[]
|
||||
* @phpstan-var array<string, FlattenInfo>
|
||||
*/
|
||||
public array $flattenedProperties = [];
|
||||
|
||||
/**
|
||||
* @var BlockStateUpgradeSchemaBlockRemap[][]
|
||||
* @phpstan-var array<string, list<BlockStateUpgradeSchemaBlockRemap>>
|
||||
@ -93,6 +100,7 @@ final class BlockStateUpgradeSchema{
|
||||
$this->removedProperties,
|
||||
$this->renamedProperties,
|
||||
$this->remappedPropertyValues,
|
||||
$this->flattenedProperties,
|
||||
$this->remappedStates,
|
||||
] as $list){
|
||||
if(count($list) !== 0){
|
||||
|
@ -40,7 +40,7 @@ final class BlockStateUpgradeSchemaBlockRemap{
|
||||
*/
|
||||
public function __construct(
|
||||
public array $oldState,
|
||||
public string|BlockStateUpgradeSchemaFlattenedName $newName,
|
||||
public string|BlockStateUpgradeSchemaFlattenInfo $newName,
|
||||
public array $newState,
|
||||
public array $copiedState
|
||||
){}
|
||||
@ -48,8 +48,8 @@ final class BlockStateUpgradeSchemaBlockRemap{
|
||||
public function equals(self $that) : bool{
|
||||
$sameName = $this->newName === $that->newName ||
|
||||
(
|
||||
$this->newName instanceof BlockStateUpgradeSchemaFlattenedName &&
|
||||
$that->newName instanceof BlockStateUpgradeSchemaFlattenedName &&
|
||||
$this->newName instanceof BlockStateUpgradeSchemaFlattenInfo &&
|
||||
$that->newName instanceof BlockStateUpgradeSchemaFlattenInfo &&
|
||||
$this->newName->equals($that->newName)
|
||||
);
|
||||
if(!$sameName){
|
||||
|
@ -23,20 +23,25 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\bedrock\block\upgrade;
|
||||
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use function ksort;
|
||||
use const SORT_STRING;
|
||||
|
||||
final class BlockStateUpgradeSchemaFlattenedName{
|
||||
final class BlockStateUpgradeSchemaFlattenInfo{
|
||||
|
||||
/**
|
||||
* @param string[] $flattenedValueRemaps
|
||||
* @phpstan-param array<string, string> $flattenedValueRemaps
|
||||
* @phpstan-param ?class-string<ByteTag|IntTag|StringTag> $flattenedPropertyType
|
||||
*/
|
||||
public function __construct(
|
||||
public string $prefix,
|
||||
public string $flattenedProperty,
|
||||
public string $suffix,
|
||||
public array $flattenedValueRemaps
|
||||
public array $flattenedValueRemaps,
|
||||
public ?string $flattenedPropertyType = null
|
||||
){
|
||||
ksort($this->flattenedValueRemaps, SORT_STRING);
|
||||
}
|
||||
@ -45,6 +50,7 @@ final class BlockStateUpgradeSchemaFlattenedName{
|
||||
return $this->prefix === $that->prefix &&
|
||||
$this->flattenedProperty === $that->flattenedProperty &&
|
||||
$this->suffix === $that->suffix &&
|
||||
$this->flattenedValueRemaps === $that->flattenedValueRemaps;
|
||||
$this->flattenedValueRemaps === $that->flattenedValueRemaps &&
|
||||
$this->flattenedPropertyType === $that->flattenedPropertyType;
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ namespace pocketmine\data\bedrock\block\upgrade;
|
||||
|
||||
use pocketmine\data\bedrock\block\upgrade\model\BlockStateUpgradeSchemaModel;
|
||||
use pocketmine\data\bedrock\block\upgrade\model\BlockStateUpgradeSchemaModelBlockRemap;
|
||||
use pocketmine\data\bedrock\block\upgrade\model\BlockStateUpgradeSchemaModelFlattenedName;
|
||||
use pocketmine\data\bedrock\block\upgrade\model\BlockStateUpgradeSchemaModelFlattenInfo;
|
||||
use pocketmine\data\bedrock\block\upgrade\model\BlockStateUpgradeSchemaModelTag;
|
||||
use pocketmine\data\bedrock\block\upgrade\model\BlockStateUpgradeSchemaModelValueRemap;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
@ -155,20 +155,24 @@ final class BlockStateUpgradeSchemaUtils{
|
||||
}
|
||||
}
|
||||
|
||||
foreach(Utils::stringifyKeys($model->flattenedProperties ?? []) as $blockName => $flattenRule){
|
||||
$result->flattenedProperties[$blockName] = self::jsonModelToFlattenRule($flattenRule);
|
||||
}
|
||||
|
||||
foreach(Utils::stringifyKeys($model->remappedStates ?? []) as $oldBlockName => $remaps){
|
||||
foreach($remaps as $remap){
|
||||
if(isset($remap->newName) === isset($remap->newFlattenedName)){
|
||||
if(isset($remap->newName)){
|
||||
$remapName = $remap->newName;
|
||||
}elseif(isset($remap->newFlattenedName)){
|
||||
$flattenRule = $remap->newFlattenedName;
|
||||
$remapName = self::jsonModelToFlattenRule($flattenRule);
|
||||
}else{
|
||||
throw new \UnexpectedValueException("Expected exactly one of 'newName' or 'newFlattenedName' properties to be set");
|
||||
}
|
||||
|
||||
$result->remappedStates[$oldBlockName][] = new BlockStateUpgradeSchemaBlockRemap(
|
||||
array_map(fn(BlockStateUpgradeSchemaModelTag $tag) => self::jsonModelToTag($tag), $remap->oldState ?? []),
|
||||
$remap->newName ?? new BlockStateUpgradeSchemaFlattenedName(
|
||||
$remap->newFlattenedName->prefix,
|
||||
$remap->newFlattenedName->flattenedProperty,
|
||||
$remap->newFlattenedName->suffix,
|
||||
$remap->newFlattenedName->flattenedValueRemaps ?? [],
|
||||
),
|
||||
$remapName,
|
||||
array_map(fn(BlockStateUpgradeSchemaModelTag $tag) => self::jsonModelToTag($tag), $remap->newState ?? []),
|
||||
$remap->copiedState ?? []
|
||||
);
|
||||
@ -254,6 +258,36 @@ final class BlockStateUpgradeSchemaUtils{
|
||||
$model->remappedPropertyValues = $modelDedupMapping;
|
||||
}
|
||||
|
||||
private static function flattenRuleToJsonModel(BlockStateUpgradeSchemaFlattenInfo $flattenRule) : BlockStateUpgradeSchemaModelFlattenInfo{
|
||||
return new BlockStateUpgradeSchemaModelFlattenInfo(
|
||||
$flattenRule->prefix,
|
||||
$flattenRule->flattenedProperty,
|
||||
$flattenRule->suffix,
|
||||
$flattenRule->flattenedValueRemaps,
|
||||
match($flattenRule->flattenedPropertyType){
|
||||
StringTag::class => null, //omit for TAG_String, as this is the common case
|
||||
ByteTag::class => "byte",
|
||||
IntTag::class => "int",
|
||||
default => throw new \LogicException("Unexpected tag type " . $flattenRule->flattenedPropertyType . " in flattened property type")
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static function jsonModelToFlattenRule(BlockStateUpgradeSchemaModelFlattenInfo $flattenRule) : BlockStateUpgradeSchemaFlattenInfo{
|
||||
return new BlockStateUpgradeSchemaFlattenInfo(
|
||||
$flattenRule->prefix,
|
||||
$flattenRule->flattenedProperty,
|
||||
$flattenRule->suffix,
|
||||
$flattenRule->flattenedValueRemaps ?? [],
|
||||
match ($flattenRule->flattenedPropertyType) {
|
||||
"string", null => StringTag::class,
|
||||
"int" => IntTag::class,
|
||||
"byte" => ByteTag::class,
|
||||
default => throw new \UnexpectedValueException("Unexpected flattened property type $flattenRule->flattenedPropertyType, expected 'string', 'int' or 'byte'")
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public static function toJsonModel(BlockStateUpgradeSchema $schema) : BlockStateUpgradeSchemaModel{
|
||||
$result = new BlockStateUpgradeSchemaModel();
|
||||
$result->maxVersionMajor = $schema->maxVersionMajor;
|
||||
@ -292,19 +326,19 @@ final class BlockStateUpgradeSchemaUtils{
|
||||
|
||||
self::buildRemappedValuesIndex($schema, $result);
|
||||
|
||||
foreach(Utils::stringifyKeys($schema->flattenedProperties) as $blockName => $flattenRule){
|
||||
$result->flattenedProperties[$blockName] = self::flattenRuleToJsonModel($flattenRule);
|
||||
}
|
||||
if(isset($result->flattenedProperties)){
|
||||
ksort($result->flattenedProperties);
|
||||
}
|
||||
|
||||
foreach(Utils::stringifyKeys($schema->remappedStates) as $oldBlockName => $remaps){
|
||||
$keyedRemaps = [];
|
||||
foreach($remaps as $remap){
|
||||
$modelRemap = new BlockStateUpgradeSchemaModelBlockRemap(
|
||||
array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->oldState),
|
||||
is_string($remap->newName) ?
|
||||
$remap->newName :
|
||||
new BlockStateUpgradeSchemaModelFlattenedName(
|
||||
$remap->newName->prefix,
|
||||
$remap->newName->flattenedProperty,
|
||||
$remap->newName->suffix,
|
||||
$remap->newName->flattenedValueRemaps
|
||||
),
|
||||
is_string($remap->newName) ? $remap->newName : self::flattenRuleToJsonModel($remap->newName),
|
||||
array_map(fn(Tag $tag) => self::tagToJsonModel($tag), $remap->newState),
|
||||
$remap->copiedState
|
||||
);
|
||||
|
@ -24,10 +24,14 @@ declare(strict_types=1);
|
||||
namespace pocketmine\data\bedrock\block\upgrade;
|
||||
|
||||
use pocketmine\data\bedrock\block\BlockStateData;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\nbt\tag\Tag;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Utils;
|
||||
use function count;
|
||||
use function get_class;
|
||||
use function is_string;
|
||||
use function ksort;
|
||||
use function max;
|
||||
@ -79,6 +83,8 @@ final class BlockStateUpgrader{
|
||||
* version doesn't tell us which of the schemas have already been applied.
|
||||
* If there's only one schema for a version (the norm), we can safely assume it's already been applied if
|
||||
* the version is the same, and skip over it.
|
||||
* TODO: this causes issues when testing isolated schemas since there will only be one schema for a version.
|
||||
* The second check should be disabled for that case.
|
||||
*/
|
||||
if($version > $resultVersion || (count($schemaList) === 1 && $version === $resultVersion)){
|
||||
continue;
|
||||
@ -104,10 +110,21 @@ final class BlockStateUpgrader{
|
||||
}
|
||||
|
||||
$oldName = $blockStateData->getName();
|
||||
$newName = $schema->renamedIds[$oldName] ?? null;
|
||||
$states = $blockStateData->getStates();
|
||||
|
||||
if(isset($schema->renamedIds[$oldName]) && isset($schema->flattenedProperties[$oldName])){
|
||||
//TODO: this probably ought to be validated when the schema is constructed
|
||||
throw new AssumptionFailedError("Both renamedIds and flattenedProperties are set for the same block ID \"$oldName\" - don't know what to do");
|
||||
}
|
||||
if(isset($schema->renamedIds[$oldName])){
|
||||
$newName = $schema->renamedIds[$oldName] ?? null;
|
||||
}elseif(isset($schema->flattenedProperties[$oldName])){
|
||||
[$newName, $states] = $this->applyPropertyFlattened($schema->flattenedProperties[$oldName], $oldName, $states);
|
||||
}else{
|
||||
$newName = null;
|
||||
}
|
||||
|
||||
$stateChanges = 0;
|
||||
$states = $blockStateData->getStates();
|
||||
|
||||
$states = $this->applyPropertyAdded($schema, $oldName, $states, $stateChanges);
|
||||
$states = $this->applyPropertyRemoved($schema, $oldName, $states, $stateChanges);
|
||||
@ -140,15 +157,8 @@ final class BlockStateUpgrader{
|
||||
if(is_string($remap->newName)){
|
||||
$newName = $remap->newName;
|
||||
}else{
|
||||
$flattenedValue = $oldState[$remap->newName->flattenedProperty] ?? null;
|
||||
if($flattenedValue instanceof StringTag){
|
||||
$embedValue = $remap->newName->flattenedValueRemaps[$flattenedValue->getValue()] ?? $flattenedValue->getValue();
|
||||
$newName = sprintf("%s%s%s", $remap->newName->prefix, $embedValue, $remap->newName->suffix);
|
||||
unset($oldState[$remap->newName->flattenedProperty]);
|
||||
}else{
|
||||
//flattened property is not a TAG_String, so this transformation is not applicable
|
||||
continue;
|
||||
}
|
||||
//discard flatten modifications to state - the remap newState and copiedState will take care of it
|
||||
[$newName, ] = $this->applyPropertyFlattened($remap->newName, $oldName, $oldState);
|
||||
}
|
||||
|
||||
$newState = $remap->newState;
|
||||
@ -266,4 +276,32 @@ final class BlockStateUpgrader{
|
||||
|
||||
return $states;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tag[] $states
|
||||
* @phpstan-param array<string, Tag> $states
|
||||
*
|
||||
* @return (string|Tag[])[]
|
||||
* @phpstan-return array{0: string, 1: array<string, Tag>}
|
||||
*/
|
||||
private function applyPropertyFlattened(BlockStateUpgradeSchemaFlattenInfo $flattenInfo, string $oldName, array $states) : array{
|
||||
$flattenedValue = $states[$flattenInfo->flattenedProperty] ?? null;
|
||||
$expectedType = $flattenInfo->flattenedPropertyType;
|
||||
if(!$flattenedValue instanceof $expectedType){
|
||||
//flattened property is not of the expected type, so this transformation is not applicable
|
||||
return [$oldName, $states];
|
||||
}
|
||||
$embedKey = match(get_class($flattenedValue)){
|
||||
StringTag::class => $flattenedValue->getValue(),
|
||||
ByteTag::class => (string) $flattenedValue->getValue(),
|
||||
IntTag::class => (string) $flattenedValue->getValue(),
|
||||
//flattenedPropertyType is always one of these three types, but PHPStan doesn't know that
|
||||
default => throw new AssumptionFailedError("flattenedPropertyType should be one of these three types, but have " . get_class($flattenedValue)),
|
||||
};
|
||||
$embedValue = $flattenInfo->flattenedValueRemaps[$embedKey] ?? $embedKey;
|
||||
$newName = sprintf("%s%s%s", $flattenInfo->prefix, $embedValue, $flattenInfo->suffix);
|
||||
unset($states[$flattenInfo->flattenedProperty]);
|
||||
|
||||
return [$newName, $states];
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user