diff --git a/.github/workflows/branch-sync-cron-trigger.yml b/.github/workflows/branch-sync-cron-trigger.yml
new file mode 100644
index 000000000..145fcd222
--- /dev/null
+++ b/.github/workflows/branch-sync-cron-trigger.yml
@@ -0,0 +1,32 @@
+#Since GitHub automatically disables cron actions after 60 days of repo inactivity, we need the active repo (PM)
+#to trigger the branch merge workflow explicitly. This avoids the need for TOS-violating actions which we previously
+#used to keep the restricted action active, as the workflow depends on the activity of this repo anyway.
+
+name: Trigger branch sync
+
+on:
+ schedule:
+ - cron: "0 0 * * *" #once per day so we don't spam merge commits on busy days
+ workflow_dispatch: #for testing
+
+jobs:
+ trigger:
+ name: Trigger branch sync RestrictedActions workflow
+ runs-on: ubuntu-22.04
+
+ steps:
+ - name: Generate access token
+ id: generate-token
+ uses: actions/create-github-app-token@v2
+ with:
+ app-id: ${{ vars.RESTRICTED_ACTIONS_DISPATCH_ID }}
+ private-key: ${{ secrets.RESTRICTED_ACTIONS_DISPATCH_KEY }}
+ owner: ${{ github.repository_owner }}
+ repositories: RestrictedActions
+
+ - name: Dispatch branch sync restricted action
+ uses: peter-evans/repository-dispatch@v3
+ with:
+ token: ${{ steps.generate-token.outputs.token }}
+ repository: ${{ github.repository_owner }}/RestrictedActions
+ event-type: pocketmine_mp_branch_sync
diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml
index 83d568878..acfc3d3a7 100644
--- a/.github/workflows/build-docker-image.yml
+++ b/.github/workflows/build-docker-image.yml
@@ -4,6 +4,11 @@ on:
release:
types:
- published
+ workflow_dispatch:
+ inputs:
+ release:
+ description: 'Tag name to build'
+ required: true
jobs:
build:
@@ -28,16 +33,28 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Clone pmmp/PocketMine-Docker repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
repository: pmmp/PocketMine-Docker
fetch-depth: 1
- - name: Get tag names
+
+ - name: Get tag name
id: tag-name
run: |
- VERSION=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{')
- echo TAG_NAME=$VERSION >> $GITHUB_OUTPUT
+ if [[ "${{ github.event_name }}" == "release" ]]; then
+ echo TAG_NAME="${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT
+ elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
+ echo TAG_NAME="${{ github.event.inputs.release }}" >> $GITHUB_OUTPUT
+ else
+ echo "Unsupported event type: ${{ github.event_name }}"
+ exit 1
+ fi
+
+ - name: Parse version
+ id: version
+ run: |
+ VERSION="${{ steps.tag-name.outputs.TAG_NAME }}"
echo MAJOR=$(echo $VERSION | cut -d. -f1) >> $GITHUB_OUTPUT
echo MINOR=$(echo $VERSION | cut -d. -f1-2) >> $GITHUB_OUTPUT
@@ -53,7 +70,7 @@ jobs:
run: echo NAME=$(echo "${GITHUB_REPOSITORY,,}") >> $GITHUB_OUTPUT
- name: Build image for tag
- uses: docker/build-push-action@v6.15.0
+ uses: docker/build-push-action@v6.18.0
with:
push: true
context: ./pocketmine-mp
@@ -66,33 +83,33 @@ jobs:
- name: Build image for major tag
if: steps.channel.outputs.CHANNEL == 'stable'
- uses: docker/build-push-action@v6.15.0
+ uses: docker/build-push-action@v6.18.0
with:
push: true
context: ./pocketmine-mp
tags: |
- ${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MAJOR }}
- ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MAJOR }}
+ ${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.version.outputs.MAJOR }}
+ ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.version.outputs.MAJOR }}
build-args: |
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
PMMP_REPO=${{ github.repository }}
- name: Build image for minor tag
if: steps.channel.outputs.CHANNEL == 'stable'
- uses: docker/build-push-action@v6.15.0
+ uses: docker/build-push-action@v6.18.0
with:
push: true
context: ./pocketmine-mp
tags: |
- ${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MINOR }}
- ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MINOR }}
+ ${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.version.outputs.MINOR }}
+ ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.version.outputs.MINOR }}
build-args: |
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
PMMP_REPO=${{ github.repository }}
- name: Build image for latest tag
if: steps.channel.outputs.CHANNEL == 'stable'
- uses: docker/build-push-action@v6.15.0
+ uses: docker/build-push-action@v6.18.0
with:
push: true
context: ./pocketmine-mp
diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml
new file mode 100644
index 000000000..c644876e0
--- /dev/null
+++ b/.github/workflows/copilot-setup-steps.yml
@@ -0,0 +1,47 @@
+name: "Copilot Agent environment setup"
+
+on:
+ workflow_dispatch:
+ push:
+ paths:
+ - .github/workflows/copilot-setup-steps.yml
+ pull_request:
+ paths:
+ - .github/workflows/copilot-setup-steps.yml
+
+jobs:
+ # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
+ copilot-setup-steps:
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+
+ steps:
+ - uses: actions/checkout@v5
+
+ - name: Setup PHP
+ uses: pmmp/setup-php-action@3.2.0
+ with:
+ php-version: 8.3
+ install-path: "./bin"
+ pm-version-major: 5
+
+ - name: Restore Composer package cache
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cache/composer/files
+ ~/.cache/composer/vcs
+ key: "composer-v2-cache-8.3-${{ hashFiles('./composer.lock') }}"
+ restore-keys: |
+ composer-v2-cache-
+
+ - name: Install Composer dependencies
+ run: composer install --prefer-dist --no-interaction
+
+ - name: Clone extension stubs
+ uses: actions/checkout@v5
+ with:
+ repository: pmmp/phpstorm-stubs
+ path: extension-stubs
diff --git a/.github/workflows/discord-release-notify.yml b/.github/workflows/discord-release-notify.yml
index fde5e3099..c0aed1320 100644
--- a/.github/workflows/discord-release-notify.yml
+++ b/.github/workflows/discord-release-notify.yml
@@ -4,18 +4,23 @@ on:
release:
types:
- published
+ workflow_dispatch:
+ inputs:
+ release:
+ description: 'Release to make notification for'
+ required: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Setup PHP and tools
- uses: shivammathur/setup-php@2.32.0
+ uses: shivammathur/setup-php@2.35.3
with:
- php-version: 8.2
+ php-version: 8.3
- name: Restore Composer package cache
uses: actions/cache@v4
@@ -30,9 +35,17 @@ jobs:
- name: Install Composer dependencies
run: composer install --no-dev --prefer-dist --no-interaction --ignore-platform-reqs
- - name: Get actual tag name
+ - name: Get tag name
id: tag-name
- run: echo TAG_NAME=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{') >> $GITHUB_OUTPUT
+ run: |
+ if [[ "${{ github.event_name }}" == "release" ]]; then
+ echo TAG_NAME="${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT
+ elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
+ echo TAG_NAME="${{ github.event.inputs.release }}" >> $GITHUB_OUTPUT
+ else
+ echo "Unsupported event type: ${{ github.event_name }}"
+ exit 1
+ fi
- name: Run webhook post script
run: php .github/workflows/discord-release-embed.php ${{ github.repository }} ${{ steps.tag-name.outputs.TAG_NAME }} ${{ github.token }} ${{ secrets.DISCORD_RELEASE_WEBHOOK }} ${{ secrets.DISCORD_NEWS_PING_ROLE_ID }}
diff --git a/.github/workflows/draft-release-pr-check.yml b/.github/workflows/draft-release-pr-check.yml
index 303f61ccf..4410d4dee 100644
--- a/.github/workflows/draft-release-pr-check.yml
+++ b/.github/workflows/draft-release-pr-check.yml
@@ -30,7 +30,7 @@ jobs:
valid: ${{ steps.validate.outputs.DEV_BUILD == 'false' }}
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Check IS_DEVELOPMENT_BUILD flag
id: validate
@@ -46,12 +46,12 @@ jobs:
runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Setup PHP
- uses: shivammathur/setup-php@2.32.0
+ uses: shivammathur/setup-php@2.35.3
with:
- php-version: 8.2
+ php-version: 8.3
- name: Restore Composer package cache
uses: actions/cache@v4
diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml
index 02cdeec6f..c72dd5688 100644
--- a/.github/workflows/draft-release.yml
+++ b/.github/workflows/draft-release.yml
@@ -18,7 +18,7 @@ on:
- "*"
env:
- PHP_VERSION: "8.2"
+ PHP_VERSION: "8.3"
jobs:
skip:
@@ -59,7 +59,7 @@ jobs:
steps:
- name: Generate access token
id: generate-token
- uses: actions/create-github-app-token@v1
+ uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.RESTRICTED_ACTIONS_DISPATCH_ID }}
private-key: ${{ secrets.RESTRICTED_ACTIONS_DISPATCH_KEY }}
@@ -82,12 +82,12 @@ jobs:
runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
submodules: true
- name: Setup PHP
- uses: shivammathur/setup-php@2.32.0
+ uses: shivammathur/setup-php@2.35.3
with:
php-version: ${{ env.PHP_VERSION }}
@@ -165,7 +165,7 @@ jobs:
${{ github.workspace }}/core-permissions.rst
- name: Create draft release
- uses: ncipollo/release-action@v1.16.0
+ uses: ncipollo/release-action@v1.18.0
id: create-draft
with:
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json,${{ github.workspace }}/core-permissions.rst
@@ -188,4 +188,4 @@ jobs:
if: github.event_name == 'pull_request_target'
uses: thollander/actions-comment-pull-request@v3
with:
- message: "[Draft release ${{ steps.get-pm-version.outputs.PM_VERSION }}](${{ steps.create-draft.outputs.html_url }}) has been created for commit ${{ github.sha }}. Please review and publish it."
+ message: "${{ vars.DRAFT_RELEASE_NOTIFICATION_MENTION }} [Draft release ${{ steps.get-pm-version.outputs.PM_VERSION }}](${{ steps.create-draft.outputs.html_url }}) has been created for commit ${{ github.sha }}. Please review and publish it."
diff --git a/.github/workflows/main-php-matrix.yml b/.github/workflows/main-php-matrix.yml
index 015a33188..7637a3956 100644
--- a/.github/workflows/main-php-matrix.yml
+++ b/.github/workflows/main-php-matrix.yml
@@ -27,7 +27,7 @@ jobs:
fail-fast: false
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Setup PHP
uses: pmmp/setup-php-action@3.2.0
@@ -59,7 +59,7 @@ jobs:
fail-fast: false
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Setup PHP
uses: pmmp/setup-php-action@3.2.0
@@ -91,7 +91,7 @@ jobs:
fail-fast: false
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
submodules: true
@@ -125,7 +125,7 @@ jobs:
fail-fast: false
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Setup PHP
uses: pmmp/setup-php-action@3.2.0
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 051a3a790..44093b707 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- php: ["8.1", "8.2", "8.3"]
+ php: ["8.3"]
uses: ./.github/workflows/main-php-matrix.yml
with:
@@ -25,13 +25,13 @@ jobs:
fail-fast: false
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Setup PHP and tools
- uses: shivammathur/setup-php@2.32.0
+ uses: shivammathur/setup-php@2.35.3
with:
- php-version: 8.2
- tools: php-cs-fixer:3.49
+ php-version: 8.3
+ tools: php-cs-fixer:3.75
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -45,7 +45,7 @@ jobs:
fail-fast: false
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@2.0.0
diff --git a/.github/workflows/pr-remove-waiting-label.yml b/.github/workflows/pr-remove-waiting-label.yml
index eb46043bd..b7cd85acd 100644
--- a/.github/workflows/pr-remove-waiting-label.yml
+++ b/.github/workflows/pr-remove-waiting-label.yml
@@ -15,19 +15,23 @@ jobs:
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;
+ async function removeLabel(owner, repo, issue_number, name) {
+ try {
+ await github.rest.issues.removeLabel({
+ owner: owner,
+ repo: repo,
+ issue_number: issue_number,
+ name: name,
+ });
+ } catch (error) {
+ if (error.status === 404) {
+ //probably label wasn't set on the issue
+ console.log('Failed to remove label ' + name + ' (probably label isn\'t on the PR): ' + error.message);
+ } else {
+ throw error;
+ }
}
}
+ const [owner, repo] = context.payload.repository.full_name.split('/');
+ removeLabel(owner, repo, context.payload.number, "Status: Waiting on Author");
+ removeLabel(owner, repo, context.payload.number, "Stale");
diff --git a/.github/workflows/team-pr-auto-approve.yml b/.github/workflows/team-pr-auto-approve.yml
index 0c2fdd81c..cc5c47139 100644
--- a/.github/workflows/team-pr-auto-approve.yml
+++ b/.github/workflows/team-pr-auto-approve.yml
@@ -22,7 +22,7 @@ jobs:
steps:
- name: Generate access token
id: generate-token
- uses: actions/create-github-app-token@v1
+ uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.RESTRICTED_ACTIONS_DISPATCH_ID }}
private-key: ${{ secrets.RESTRICTED_ACTIONS_DISPATCH_KEY }}
diff --git a/.github/workflows/update-updater-api.yml b/.github/workflows/update-updater-api.yml
index 3f42062fd..841fa7d44 100644
--- a/.github/workflows/update-updater-api.yml
+++ b/.github/workflows/update-updater-api.yml
@@ -4,6 +4,11 @@ on:
release:
types:
- published
+ workflow_dispatch:
+ inputs:
+ release:
+ description: 'Release to publish info for'
+ required: true
jobs:
build:
@@ -14,14 +19,22 @@ jobs:
- name: Install jq
run: sudo apt update && sudo apt install jq -y
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
repository: ${{ github.repository_owner }}/update.pmmp.io
ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }}
- - name: Get actual tag name
+ - name: Get tag name
id: tag-name
- run: echo TAG_NAME=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{') >> $GITHUB_OUTPUT
+ run: |
+ if [[ "${{ github.event_name }}" == "release" ]]; then
+ echo TAG_NAME="${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT
+ elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
+ echo TAG_NAME="${{ github.event.inputs.release }}" >> $GITHUB_OUTPUT
+ else
+ echo "Unsupported event type: ${{ github.event_name }}"
+ exit 1
+ fi
- name: Download new release information
run: curl -f -L ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.tag-name.outputs.TAG_NAME }}/build_info.json -o new_build_info.json
diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php
index 2effafe17..81221c11c 100644
--- a/.php-cs-fixer.php
+++ b/.php-cs-fixer.php
@@ -5,6 +5,13 @@ $finder = PhpCsFixer\Finder::create()
->in(__DIR__ . '/build')
->in(__DIR__ . '/tests')
->in(__DIR__ . '/tools')
+
+ //JsonMapper will break if the FQNs in the doc comments for these are shortened :(
+ ->notPath('crafting/json')
+ ->notPath('inventory/json')
+ ->notPath('data/bedrock/block/upgrade/model')
+ ->notPath('data/bedrock/item/upgrade/model')
+
->notName('PocketMine.php');
return (new PhpCsFixer\Config)
diff --git a/README.md b/README.md
index 6f2b715ab..98f569346 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
-
+
diff --git a/build/dump-version-info.php b/build/dump-version-info.php
index e13696f3d..3181acba6 100644
--- a/build/dump-version-info.php
+++ b/build/dump-version-info.php
@@ -31,8 +31,8 @@ require dirname(__DIR__) . '/vendor/autoload.php';
*/
/**
- * @var string[]|\Closure[] $options
- * @phpstan-var array $options
+ * @var string[]|Closure[] $options
+ * @phpstan-var array $options
*/
$options = [
"base_version" => VersionInfo::BASE_VERSION,
diff --git a/build/php b/build/php
index 154943379..ce1b095a9 160000
--- a/build/php
+++ b/build/php
@@ -1 +1 @@
-Subproject commit 15494337976e645499e2e3e8c8b491227522be91
+Subproject commit ce1b095a9c6f47dadc7b5812da4e469d52f272bc
diff --git a/changelogs/5.28.md b/changelogs/5.28.md
new file mode 100644
index 000000000..f378031f7
--- /dev/null
+++ b/changelogs/5.28.md
@@ -0,0 +1,34 @@
+# 5.28.0
+Released 9th May 2025.
+
+This is a support release for Minecraft: Bedrock Edition 1.21.80.
+
+**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.80.
+- Removed support for earlier versions.
+
+## Fixes
+- `AvailableEnchantmentRegistry` now requires provided tags to always be `string`. Previously, this wasn't enforced, leading to random crashes in core code related to enchanting.
+- `Entity->setFireTicks()` and `Entity->setOnFire()` now truncate the fire time to the max value instead of throwing exceptions.
+
+## Internals
+- Improved PHPStan error reporting for unsafe foreaches. Foreach on an array with implicit keys now generates different errors than foreach on an array with string keys.
+
+# 5.28.1
+Released 17th May 2025.
+
+## Fixes
+- Fixed errors when PlayStation players attempt to join due to null `TitleID`.
+
+# 5.28.2
+Released 17th May 2025.
+
+## Fixes
+- Fixed version constraints which were incorrectly updated during the 1.21.80 update. This led to an unnoticed failure to update BedrockProtocol in the previous patch release.
+- Actually fixed PlayStation issues this time
diff --git a/changelogs/5.29.md b/changelogs/5.29.md
new file mode 100644
index 000000000..cb6e50da3
--- /dev/null
+++ b/changelogs/5.29.md
@@ -0,0 +1,25 @@
+# 5.29.0
+Released 18th June 2025.
+
+This is a support release for Minecraft: Bedrock Edition 1.21.90.
+
+**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.90.
+- Removed support for earlier versions.
+
+## Fixes
+- Fixed thread crashes sometimes not reporting proper cause information in crashdumps.
+- Fixed crash when a plugin replaced a player's held tool with a different tool with a damage exceeding the old tool's max damage during an action.
+- Fixed performance issue of `PlayerAuthInputPacket` input flags handling (broken change detection).
+- Fixed `BaseInventory->addItem()` triggering updates on empty slots when no items were added.
+- Fixed slow check in `SubChunk` block layer garbage collection.
+
+## Internals
+- `LoginPacketHandler->processLogin()` signature has changed. This will break any plugins overriding `LoginPacketHandler`. As noted above, this is _not_ covered by the API version guarantee.
+- Automated branch sync for `minor-next` and `major-next` is now triggered by `repository_dispatch` from a cron job in this repository instead of `RestrictedActions`. The `RestrictedActions` cron job was getting automatically disabled by GitHub due to repo inactivity.
diff --git a/changelogs/5.30.md b/changelogs/5.30.md
new file mode 100644
index 000000000..cc2ecbc1f
--- /dev/null
+++ b/changelogs/5.30.md
@@ -0,0 +1,73 @@
+# 5.30.0
+Released 18th June 2025.
+
+This is a minor feature release containing API additions, internals cleanup and user experience improvements.
+
+**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
+Do not update plugin minimum API versions unless you need new features added in this release.
+
+**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
+Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
+
+## General
+- Significantly reduced log spam when unknown blocks, tiles and entities are found in saved worlds.
+- The file name structure for crashdumps has been changed to improve sorting order in file browsers.
+- Buffering is now skipped on the RakLib layer. In theory this could reduce player network latency by 10 ms (YMMV).
+
+## Gameplay
+### Blocks
+- Many blocks have had their hardness and blast resistance updated to match vanilla.
+- Implemented Respawn Anchor.
+- Melon Stem and Pumpkin Stem drop amounts should now match vanilla (using binomial distribution).
+
+## API
+## General
+- Verification of save registration has been added for blocks, entities and tiles. This is intended to make it easier to find mistakes when registering custom things, which previously would produce obscure core crashes.
+
+### `pocketmine\event\block`
+- The following classes have been added:
+ - `BlockPreExplodeEvent` - called before a block tries to explode
+ - `BlockExplodeEvent` - called when after a block's explosion calculation has been done, but before any changes are applied
+
+### `pocketmine\event\entity`
+- The following classes have been added:
+ - `EntityExtinguishEvent` - called when a burning entity is extinguished by water or other sources
+ - `EntityFrostWalkerEvent` - called every tick upon which an entity wearing Frost Walker boots moves; this can be used to customise or cancel the behaviour of the Frost Walker enchantment
+
+### `pocketmine\event\player`
+- The following classes have been added:
+ - `PlayerRespawnAnchorUseEvent` - called when a player interacts with a charged respawn anchor
+
+### `pocketmine\entity`
+- The following methods have been added:
+ - `public Entity->getStepHeight() : float`
+ - `public Entity->setStepHeight(float $stepHeight) : void`
+
+### `pocketmine\world\generator`
+- Generator execution has been decoupled from `PopulationTask` and async tasks in general. The following classes have been added:
+ - `executor\GeneratorExecutor`
+ - `executor\SyncGeneratorExecutor` - runs a generator on the main thread (used for flat world generation, which doesn't need threads)
+ - `executor\AsyncGeneratorExecutor` - runs a generator inside an async task, as before
+ - `PopulationUtils` - contains population business logic previously baked into `PopulationTask` - this permits the reuse of that logic outside async tasks
+- The following methods have signature changes:
+ - `GeneratorManager->addGenerator()` now accepts an optional `bool $fast` parameter, defaulting to `false`; setting this to `true` will cause your generator to run on the main thread
+- The following methods have been added:
+ - `public GeneratorManagerEntry->isFast() : bool` - returns whether this generator should run on the main thread
+- `PopulationTask` has been marked as `@internal`. In the next major version, it will move to the `generator\executor` namespace; however, for now it stays put because plugins currently have no other way to regenerate chunks.
+
+## Internals
+- World data version numbers have been consolidated in `pocketmine\data\bedrock\WorldDataVersions`. This removes the need to modify several different files to support new world versions, and reduces the chances of things getting missed.
+- Block hardness and blast resistance is now unit-tested against `block_properties_table.json` in `BedrockData`. This file comes from vanilla BDS, so we can use it to verify compliance.
+- Protocol-layer "server auth block breaking" has been enabled. Functionally, this is no different from the previous system, it just works differently on the network layer.
+- Various internal classes in the `pocketmine\world\generator` namespace have been moved to the `generator\executor` namespace.
+- Removed `World->registerGenerator()` and `World->unregisterGenerator()`.
+- Removed redundant calls to `curl_close()` (obsolete since PHP 8.0).
+
+# 5.30.1
+Released 23rd June 2025.
+
+## Fixes
+- Fixed accidental break of backwards compatibility in `EntityExplodeEvent` introduced in the previous release.
+- Fixed placement of player holding block when exploding respawn anchor.
+- Updated BedrockProtocol to fix incorrect encoding of `ServerScriptDebugDrawerPacket`.
+- Disabled client-side locator bar, allowing plugins to write their own implementations.
diff --git a/changelogs/5.31.md b/changelogs/5.31.md
new file mode 100644
index 000000000..60e797425
--- /dev/null
+++ b/changelogs/5.31.md
@@ -0,0 +1,14 @@
+# 5.31.0
+Released 8th July 2025.
+
+This is a support release for Minecraft: Bedrock Edition 1.21.93.
+
+**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.93.
+- Removed support for earlier versions.
diff --git a/changelogs/5.32.md b/changelogs/5.32.md
new file mode 100644
index 000000000..414330351
--- /dev/null
+++ b/changelogs/5.32.md
@@ -0,0 +1,25 @@
+# 5.32.0
+Released 6th August 2025.
+
+This is a support release for Minecraft: Bedrock Edition 1.21.100.
+
+**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.100.
+- Removed support for earlier versions.
+
+## Fixes
+- Fixed deadlock on RakLib thread crash (e.g. due to port binding failure).
+
+# 5.32.1
+Released 14th August 2025.
+
+## Fixes
+- Hardened checks when processing resource pack sending during player logins.
+- Fixed content log warning about crafting recipe with missing ID.
+- Fixed packets in a batch still being processed after one of them caused the session to be terminated.
diff --git a/changelogs/5.33.md b/changelogs/5.33.md
new file mode 100644
index 000000000..45f03f521
--- /dev/null
+++ b/changelogs/5.33.md
@@ -0,0 +1,129 @@
+# 5.33.0
+Released 30th August 2025.
+
+This is a minor feature release containing internals improvements, API improvements and new gameplay features.
+
+**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.
+
+## Performance
+- Worlds now remember when a chunk isn't generated. This reduces world I/O during world generation.
+- `BlockObjectToStateSerializer` now creates fewer objects in certain cases.
+
+## Gameplay
+- The following blocks have been added and/or are now properly supported:
+ - Hanging signs
+ - Illager banners
+
+## Tools
+- `generate-bedrock-data-from-packets.php` now represents items as strings directly when only an ID is present. This significantly improves readability in `BedrockData` and reduces file sizes.
+
+## API
+### `pocketmine\block`
+- Added (and implemented) interfaces for many common block properties, to allow `instanceof` to be used:
+ - `Ageable`: for blocks with age, such as crops
+ - `AnyFacing`: for blocks which can face up, down, and horizontal directions (not the same as `HorizontalFacing`!)
+ - `Colored`: for blocks with 16 `DyeColor` variants
+ - `CoralMaterial`: for coral blocks, provides access to coral type and dead/alive
+ - `HorizontalFacing`: for blocks which can **only** face horizontal directions (not the same as `AnyFacing`!)
+ - `Lightable`: for light-source blocks which can be turned on and off, e.g. redstone lamp
+ - `MultiAnyFacing`: for blocks which can appear in multiple faces of the same block (including up, down, and horizontal faces), e.g. glow lichen
+ - `PillarRotation`: for blocks which can be oriented on an axis, e.g. logs
+ - `PoweredByRedstone`: for blocks which receive power from a redstone component, e.g. redstone lamp
+ - `SignLikeRotation`: for blocks which can be rotated 16 ways, e.g. signs, banners
+ - `WoodMaterial`: for blocks made from wood
+ - These interfaces have been implemented on many blocks. For the sake of brevity, they are not listed here, but you can expect to see them wherever the corresponding traits were used.
+- The following classes have been added:
+ - `BaseOminousBanner`
+ - `CeilingCenterHangingSign` - both chains connected to the same point on the block above, can face 16 directions
+ - `CeilingEdgesHangingSign` - each chain connected to separate edges of the block above, can face 4 directions
+ - `OminousFloorBanner` - floor version of illager banner, can face 16 directions
+ - `OminousWallBanner` - wall version of illager banner, can face 4 directions
+ - `WallHangingSign` - hangs from a horizontal beam, can face 4 directions
+- The following API methods have been added:
+ - `public ChiseledBookshelf->setSlots(list $slots) : $this`
+ - `public static VanillaBlocks` methods:
+ - `ACACIA_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `ACACIA_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `ACACIA_WALL_HANGING_SIGN() : WallHangingSign`
+ - `BIRCH_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `BIRCH_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `BIRCH_WALL_HANGING_SIGN() : WallHangingSign`
+ - `CHERRY_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `CHERRY_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `CHERRY_WALL_HANGING_SIGN() : WallHangingSign`
+ - `CRIMSON_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `CRIMSON_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `CRIMSON_WALL_HANGING_SIGN() : WallHangingSign`
+ - `DARK_OAK_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `DARK_OAK_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `DARK_OAK_WALL_HANGING_SIGN() : WallHangingSign`
+ - `JUNGLE_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `JUNGLE_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `JUNGLE_WALL_HANGING_SIGN() : WallHangingSign`
+ - `MANGROVE_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `MANGROVE_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `MANGROVE_WALL_HANGING_SIGN() : WallHangingSign`
+ - `OAK_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `OAK_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `OAK_WALL_HANGING_SIGN() : WallHangingSign`
+ - `OMINOUS_FLOOR_BANNER() : OminousFloorBanner`
+ - `OMINOUS_WALL_BANNER() : OminousWallBanner`
+ - `PALE_OAK_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `PALE_OAK_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `PALE_OAK_WALL_HANGING_SIGN() : WallHangingSign`
+ - `SPRUCE_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `SPRUCE_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `SPRUCE_WALL_HANGING_SIGN() : WallHangingSign`
+ - `WARPED_CEILING_CENTER_HANGING_SIGN() : CeilingCenterHangingSign`
+ - `WARPED_CEILING_EDGES_HANGING_SIGN() : CeilingEdgesHangingSign`
+ - `WARPED_WALL_HANGING_SIGN() : WallHangingSign`
+ - `public AgeableTrait->getMaxAge() : int` (included by all growable plant-like blocks, e.g. crops)
+
+### `pocketmine\data\bedrock\block\convert`
+- A new system for symmetric block serializers and deserializers has been introduced.
+ - This allows registering both a serializer and a deserializer with the same code, meaning way less code
+ - It also eliminates information duplication and potential inconsistencies, improving maintainability.
+ - A proper way to deal with flattened IDs (e.g. color blocks) has been introduced which _doesn't_ require hardcoding a giant mess of IDs
+ - This symmetric system covers 99% of blocks which have a 1:1 association between PM and vanilla blocks, or 1:N where IDs are flattened
+ - However, there are still some special cases which require registering separate serializers and deserializers (usually in cases where the PM implementation deviates from Mojang where Mojang's implementation sucks, such as hanging signs or big dripleaf).
+ - No backwards compatibility breaks are expected as a result of this change. However, it's recommended to migrate old code to this new system for maintainability.
+ - The following new classes have been added:
+ - `BlockSerializerDeserializerRegistrar` - handles unified registration of block serializers and deserializers, based on a provided block model
+ - `FlattenedIdModel` - represents a block with some properties baked into its Minecraft ID, e.g. coral or color blocks
+ - `Model` - represents a regular block with all properties in its `states` NBT
+ - `property\BoolFromStringProperty` - property mapping a bool value from a string NBT state
+ - `property\BoolProperty`
+ - `property\CommonProperties` - singleton containing commonly-used block property definitions and groups, e.g. facing, stair properties
+ - `property\EnumFromRawStateMap` - maps a raw NBT value to a PHP `enum` and vice versa
+ - `property\IntFromRawStateMap` - maps a raw NBT value to PM integer constants and vice versa
+ - `property\IntProperty` - an integer range property with a min, max, and optional offset
+ - `property\Property` - interface implemented by all property definitions accepted by a `Model` or `FlattenedIdModel`
+ - `property\StateMap` - interface implemented by classes accepted by mapping properties, e.g. `BoolFromStringProperty`
+ - `property\StringProperty` - interface implemented by properties whose raw outputs are strings - these can be used as ID components in `FlattenedIdModel`
+ - `property\ValueFromIntProperty` - property mapping a generic PM value from an int NBT state
+ - `property\ValueFromStringProperty` - same as above, but for a string NBT state
+ - `property\ValueSetFromIntProperty` - a property mapping an `int[]` or `enum[]` from a set of flags in NBT states
+ - `property\ValueMappings` - singleton containing commonly-needed `StateMap`s
+ - The following classes have been deprecated:
+ - `BlockStateDeserializerHelper`
+ - `BlockStateSerializerHelper`
+ - The following methods have been deprecated:
+ - All methods for decoding mapped property types in `BlockStateReader`, e.g. `readFacingDirection()`
+ - All methods for encoding mapped property types in `BlockStateWriter`, e.g. `writeFacingDirection()`
+ - All specific blocktype mapping functions in `BlockStateToObjectDeserializer`, e.g. `mapStairs()`
+ - All specific blocktype mapping functions in `BlockObjectToStateSerializer`, e.g. `mapStairs()`
+
+### `pocketmine\item`
+- The following hooks have been added:
+ - `public Item->getPlacementTransaction(Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : ?BlockTransaction` - allows more complex logic for itemblocks to place blocks, without duplicating their placement conditions (used for hanging signs)
+
+### `pocketmine\world`
+- `World->setChunk()` now verifies that blockstate IDs in the provided chunk are all registered in `RuntimeBlockStateRegistry`. This should provide earlier detection for custom block registration errors by plugins.
+
+## Internals
+- `BlockStateUpgrader` is now almost entirely independent from `BlockStateData`. It's anticipated that the upgrader library will be separable from the core in the future.
+- `Block->readStateFromWorld()` is now triggered on chunk load for any position containing a tile. This should allow more effective updating of blocks with properties in their tiles.
diff --git a/composer.json b/composer.json
index 583116c0f..5d0bcbd05 100644
--- a/composer.json
+++ b/composer.json
@@ -5,7 +5,7 @@
"homepage": "https://pmmp.io",
"license": "LGPL-3.0",
"require": {
- "php": "^8.1",
+ "php": "^8.3",
"php-64bit": "*",
"ext-chunkutils2": "^0.3.1",
"ext-crypto": "^0.3.1",
@@ -34,28 +34,32 @@
"adhocore/json-comment": "~1.2.0",
"netresearch/jsonmapper": "~v5.0.0",
"pocketmine/bedrock-block-upgrade-schema": "~5.1.0+bedrock-1.21.60",
- "pocketmine/bedrock-data": "~4.1.0+bedrock-1.21.70",
- "pocketmine/bedrock-item-upgrade-schema": "~1.14.0+bedrock-1.21.50",
- "pocketmine/bedrock-protocol": "~37.0.0+bedrock-1.21.70",
+ "pocketmine/bedrock-data": "~6.0.0+bedrock-1.21.100",
+ "pocketmine/bedrock-item-upgrade-schema": "~1.15.0+bedrock-1.21.100",
+ "pocketmine/bedrock-protocol": "~40.0.0+bedrock-1.21.100",
"pocketmine/binaryutils": "^0.2.1",
- "pocketmine/callback-validator": "^1.0.2",
+ "pocketmine/callback-validator": "dev-rewrite",
"pocketmine/color": "^0.3.0",
"pocketmine/errorhandler": "^0.7.0",
- "pocketmine/locale-data": "~2.24.0",
+ "pocketmine/locale-data": "~2.25.0",
"pocketmine/log": "^0.4.0",
- "pocketmine/math": "~1.0.0",
+ "pocketmine/math": "dev-major-next as 1.0.0",
"pocketmine/nbt": "~1.1.0",
- "pocketmine/raklib": "~1.1.2",
+ "pocketmine/raklib": "~1.2.0",
"pocketmine/raklib-ipc": "~1.0.0",
"pocketmine/snooze": "^0.5.0",
- "ramsey/uuid": "~4.7.0",
- "symfony/filesystem": "~6.4.0"
+ "ramsey/uuid": "~4.9.0",
+ "symfony/filesystem": "~7.3.0"
},
"require-dev": {
- "phpstan/phpstan": "2.1.11",
+ "phpstan/phpstan": "2.1.17",
"phpstan/phpstan-phpunit": "^2.0.0",
"phpstan/phpstan-strict-rules": "^2.0.0",
- "phpunit/phpunit": "^10.5.24"
+ "phpunit/phpunit": "^12.2.1"
+ },
+ "replace": {
+ "symfony/polyfill-ctype": "*",
+ "symfony/polyfill-mbstring": "*"
},
"autoload": {
"psr-4": {
@@ -73,7 +77,7 @@
},
"config": {
"platform": {
- "php": "8.1.0"
+ "php": "8.3.0"
},
"sort-packages": true
},
diff --git a/composer.lock b/composer.lock
index 23f312317..6dd977435 100644
--- a/composer.lock
+++ b/composer.lock
@@ -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": "818c679a25da8e6b466bc454ad48dec3",
+ "content-hash": "deb7c003ba4a6101153256d5d590da42",
"packages": [
{
"name": "adhocore/json-comment",
@@ -67,16 +67,16 @@
},
{
"name": "brick/math",
- "version": "0.12.3",
+ "version": "0.13.1",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
- "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba"
+ "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba",
- "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba",
+ "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04",
+ "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04",
"shasum": ""
},
"require": {
@@ -115,7 +115,7 @@
],
"support": {
"issues": "https://github.com/brick/math/issues",
- "source": "https://github.com/brick/math/tree/0.12.3"
+ "source": "https://github.com/brick/math/tree/0.13.1"
},
"funding": [
{
@@ -123,7 +123,7 @@
"type": "github"
}
],
- "time": "2025-02-28T13:11:00+00:00"
+ "time": "2025-03-29T13:50:30+00:00"
},
{
"name": "netresearch/jsonmapper",
@@ -204,16 +204,16 @@
},
{
"name": "pocketmine/bedrock-data",
- "version": "4.1.0+bedrock-1.21.70",
+ "version": "6.0.0+bedrock-1.21.100",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockData.git",
- "reference": "d53fe98cb3b596ac016e275df5bd5e89b04a4817"
+ "reference": "edc0d829175e5e1e57c87001acfd03526c63fd34"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pmmp/BedrockData/zipball/d53fe98cb3b596ac016e275df5bd5e89b04a4817",
- "reference": "d53fe98cb3b596ac016e275df5bd5e89b04a4817",
+ "url": "https://api.github.com/repos/pmmp/BedrockData/zipball/edc0d829175e5e1e57c87001acfd03526c63fd34",
+ "reference": "edc0d829175e5e1e57c87001acfd03526c63fd34",
"shasum": ""
},
"type": "library",
@@ -224,22 +224,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.70"
+ "source": "https://github.com/pmmp/BedrockData/tree/6.0.0+bedrock-1.21.100"
},
- "time": "2025-03-25T19:43:31+00:00"
+ "time": "2025-08-30T17:25:42+00:00"
},
{
"name": "pocketmine/bedrock-item-upgrade-schema",
- "version": "1.14.0",
+ "version": "1.15.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git",
- "reference": "9fc7c9bbb558a017395c1cb7dd819c033ee971bb"
+ "reference": "09e0dbe9743f21a76b1fe04b2b4136785775f52b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/9fc7c9bbb558a017395c1cb7dd819c033ee971bb",
- "reference": "9fc7c9bbb558a017395c1cb7dd819c033ee971bb",
+ "url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/09e0dbe9743f21a76b1fe04b2b4136785775f52b",
+ "reference": "09e0dbe9743f21a76b1fe04b2b4136785775f52b",
"shasum": ""
},
"type": "library",
@@ -250,22 +250,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.14.0"
+ "source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.15.0"
},
- "time": "2024-12-04T12:22:49+00:00"
+ "time": "2025-08-06T15:08:48+00:00"
},
{
"name": "pocketmine/bedrock-protocol",
- "version": "37.0.0+bedrock-1.21.70",
+ "version": "40.0.0+bedrock-1.21.100",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
- "reference": "7091dad2c12ed4a4106432df21fc698960c6be9e"
+ "reference": "5e95cab3a6e6c24920e0c25ca4aaf887ed4b70ca"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/7091dad2c12ed4a4106432df21fc698960c6be9e",
- "reference": "7091dad2c12ed4a4106432df21fc698960c6be9e",
+ "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/5e95cab3a6e6c24920e0c25ca4aaf887ed4b70ca",
+ "reference": "5e95cab3a6e6c24920e0c25ca4aaf887ed4b70ca",
"shasum": ""
},
"require": {
@@ -296,9 +296,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/37.0.0+bedrock-1.21.70"
+ "source": "https://github.com/pmmp/BedrockProtocol/tree/40.0.0+bedrock-1.21.100"
},
- "time": "2025-03-27T15:19:36+00:00"
+ "time": "2025-08-06T15:13:45+00:00"
},
{
"name": "pocketmine/binaryutils",
@@ -344,30 +344,30 @@
},
{
"name": "pocketmine/callback-validator",
- "version": "1.0.3",
+ "version": "dev-rewrite",
"source": {
"type": "git",
"url": "https://github.com/pmmp/CallbackValidator.git",
- "reference": "64787469766bcaa7e5885242e85c23c25e8c55a2"
+ "reference": "4b9b375590872cdd98a2a07c5aa0e1e99af5ceda"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pmmp/CallbackValidator/zipball/64787469766bcaa7e5885242e85c23c25e8c55a2",
- "reference": "64787469766bcaa7e5885242e85c23c25e8c55a2",
+ "url": "https://api.github.com/repos/pmmp/CallbackValidator/zipball/4b9b375590872cdd98a2a07c5aa0e1e99af5ceda",
+ "reference": "4b9b375590872cdd98a2a07c5aa0e1e99af5ceda",
"shasum": ""
},
"require": {
"ext-reflection": "*",
- "php": "^7.1 || ^8.0"
+ "php": "^8.1"
},
"replace": {
"daverandom/callback-validator": "*"
},
"require-dev": {
"phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "0.12.59",
- "phpstan/phpstan-strict-rules": "^0.12.4",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.0"
+ "phpstan/phpstan": "2.1.0",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^9.0 || ^10.0 || ^11.0"
},
"type": "library",
"autoload": {
@@ -388,9 +388,9 @@
"description": "Fork of daverandom/callback-validator - Tools for validating callback signatures",
"support": {
"issues": "https://github.com/pmmp/CallbackValidator/issues",
- "source": "https://github.com/pmmp/CallbackValidator/tree/1.0.3"
+ "source": "https://github.com/pmmp/CallbackValidator/tree/rewrite"
},
- "time": "2020-12-11T01:45:37+00:00"
+ "time": "2025-01-03T17:50:24+00:00"
},
{
"name": "pocketmine/color",
@@ -471,16 +471,16 @@
},
{
"name": "pocketmine/locale-data",
- "version": "2.24.2",
+ "version": "2.25.1",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Language.git",
- "reference": "2a00c44c52bce98e7a43aa31517df78cbb2ba23b"
+ "reference": "8e6514f5a9638e69cdc2219c775fc7d3bb4c9fdd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pmmp/Language/zipball/2a00c44c52bce98e7a43aa31517df78cbb2ba23b",
- "reference": "2a00c44c52bce98e7a43aa31517df78cbb2ba23b",
+ "url": "https://api.github.com/repos/pmmp/Language/zipball/8e6514f5a9638e69cdc2219c775fc7d3bb4c9fdd",
+ "reference": "8e6514f5a9638e69cdc2219c775fc7d3bb4c9fdd",
"shasum": ""
},
"type": "library",
@@ -488,9 +488,9 @@
"description": "Language resources used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/Language/issues",
- "source": "https://github.com/pmmp/Language/tree/2.24.2"
+ "source": "https://github.com/pmmp/Language/tree/2.25.1"
},
- "time": "2025-04-03T01:23:27+00:00"
+ "time": "2025-04-16T11:15:32+00:00"
},
{
"name": "pocketmine/log",
@@ -535,27 +535,27 @@
},
{
"name": "pocketmine/math",
- "version": "1.0.0",
+ "version": "dev-major-next",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Math.git",
- "reference": "dc132d93595b32e9f210d78b3c8d43c662a5edbf"
+ "reference": "7513b9504e4a9d3ebde2f9d4de50266cb1dafd23"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pmmp/Math/zipball/dc132d93595b32e9f210d78b3c8d43c662a5edbf",
- "reference": "dc132d93595b32e9f210d78b3c8d43c662a5edbf",
+ "url": "https://api.github.com/repos/pmmp/Math/zipball/7513b9504e4a9d3ebde2f9d4de50266cb1dafd23",
+ "reference": "7513b9504e4a9d3ebde2f9d4de50266cb1dafd23",
"shasum": ""
},
"require": {
- "php": "^8.0",
+ "php": "^8.2",
"php-64bit": "*"
},
"require-dev": {
"phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "~1.10.3",
- "phpstan/phpstan-strict-rules": "^1.0",
- "phpunit/phpunit": "^8.5 || ^9.5"
+ "phpstan/phpstan": "2.1.0",
+ "phpstan/phpstan-strict-rules": "^2.0",
+ "phpunit/phpunit": "^10.0 || ^11.0"
},
"type": "library",
"autoload": {
@@ -570,9 +570,9 @@
"description": "PHP library containing math related code used in PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/Math/issues",
- "source": "https://github.com/pmmp/Math/tree/1.0.0"
+ "source": "https://github.com/pmmp/Math/tree/major-next"
},
- "time": "2023-08-03T12:56:33+00:00"
+ "time": "2025-08-29T18:29:53+00:00"
},
{
"name": "pocketmine/nbt",
@@ -618,16 +618,16 @@
},
{
"name": "pocketmine/raklib",
- "version": "1.1.2",
+ "version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/RakLib.git",
- "reference": "4145a31cd812fe8931c3c9c691fcd2ded2f47e7f"
+ "reference": "a28d05216d34dbd00e8aed827a58df6b4c11510b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pmmp/RakLib/zipball/4145a31cd812fe8931c3c9c691fcd2ded2f47e7f",
- "reference": "4145a31cd812fe8931c3c9c691fcd2ded2f47e7f",
+ "url": "https://api.github.com/repos/pmmp/RakLib/zipball/a28d05216d34dbd00e8aed827a58df6b4c11510b",
+ "reference": "a28d05216d34dbd00e8aed827a58df6b4c11510b",
"shasum": ""
},
"require": {
@@ -655,9 +655,9 @@
"description": "A RakNet server implementation written in PHP",
"support": {
"issues": "https://github.com/pmmp/RakLib/issues",
- "source": "https://github.com/pmmp/RakLib/tree/1.1.2"
+ "source": "https://github.com/pmmp/RakLib/tree/1.2.0"
},
- "time": "2025-04-06T03:38:21+00:00"
+ "time": "2025-06-08T17:36:06+00:00"
},
{
"name": "pocketmine/raklib-ipc",
@@ -818,21 +818,20 @@
},
{
"name": "ramsey/uuid",
- "version": "4.7.6",
+ "version": "4.9.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
- "reference": "91039bc1faa45ba123c4328958e620d382ec7088"
+ "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088",
- "reference": "91039bc1faa45ba123c4328958e620d382ec7088",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0",
+ "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0",
"shasum": ""
},
"require": {
- "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12",
- "ext-json": "*",
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13",
"php": "^8.0",
"ramsey/collection": "^1.2 || ^2.0"
},
@@ -840,26 +839,23 @@
"rhumsaa/uuid": "self.version"
},
"require-dev": {
- "captainhook/captainhook": "^5.10",
+ "captainhook/captainhook": "^5.25",
"captainhook/plugin-composer": "^5.3",
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
- "doctrine/annotations": "^1.8",
- "ergebnis/composer-normalize": "^2.15",
- "mockery/mockery": "^1.3",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "ergebnis/composer-normalize": "^2.47",
+ "mockery/mockery": "^1.6",
"paragonie/random-lib": "^2",
- "php-mock/php-mock": "^2.2",
- "php-mock/php-mock-mockery": "^1.3",
- "php-parallel-lint/php-parallel-lint": "^1.1",
- "phpbench/phpbench": "^1.0",
- "phpstan/extension-installer": "^1.1",
- "phpstan/phpstan": "^1.8",
- "phpstan/phpstan-mockery": "^1.1",
- "phpstan/phpstan-phpunit": "^1.1",
- "phpunit/phpunit": "^8.5 || ^9",
- "ramsey/composer-repl": "^1.4",
- "slevomat/coding-standard": "^8.4",
- "squizlabs/php_codesniffer": "^3.5",
- "vimeo/psalm": "^4.9"
+ "php-mock/php-mock": "^2.6",
+ "php-mock/php-mock-mockery": "^1.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpbench/phpbench": "^1.2.14",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.18",
+ "squizlabs/php_codesniffer": "^3.13"
},
"suggest": {
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
@@ -894,41 +890,31 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid/tree/4.7.6"
+ "source": "https://github.com/ramsey/uuid/tree/4.9.0"
},
- "funding": [
- {
- "url": "https://github.com/ramsey",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
- "type": "tidelift"
- }
- ],
- "time": "2024-04-27T21:32:50+00:00"
+ "time": "2025-06-25T14:20:11+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v6.4.13",
+ "version": "v7.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3"
+ "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3",
- "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
+ "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
"require-dev": {
- "symfony/process": "^5.4|^6.4|^7.0"
+ "symfony/process": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -956,7 +942,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v6.4.13"
+ "source": "https://github.com/symfony/filesystem/tree/v7.3.0"
},
"funding": [
{
@@ -972,181 +958,22 @@
"type": "tidelift"
}
],
- "time": "2024-10-25T15:07:50+00:00"
- },
- {
- "name": "symfony/polyfill-ctype",
- "version": "v1.31.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
- "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2"
- },
- "provide": {
- "ext-ctype": "*"
- },
- "suggest": {
- "ext-ctype": "For best performance"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "url": "https://github.com/symfony/polyfill",
- "name": "symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Ctype\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Gert de Pagter",
- "email": "BackEndTea@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for ctype functions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "ctype",
- "polyfill",
- "portable"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2024-09-09T11:45:10+00:00"
- },
- {
- "name": "symfony/polyfill-mbstring",
- "version": "v1.31.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
- "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2"
- },
- "provide": {
- "ext-mbstring": "*"
- },
- "suggest": {
- "ext-mbstring": "For best performance"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "url": "https://github.com/symfony/polyfill",
- "name": "symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Mbstring\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for the Mbstring extension",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "mbstring",
- "polyfill",
- "portable",
- "shim"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2024-10-25T15:15:23+00:00"
}
],
"packages-dev": [
{
"name": "myclabs/deep-copy",
- "version": "1.13.0",
+ "version": "1.13.1",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "024473a478be9df5fdaca2c793f2232fe788e414"
+ "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
- "reference": "024473a478be9df5fdaca2c793f2232fe788e414",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c",
+ "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c",
"shasum": ""
},
"require": {
@@ -1185,7 +1012,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
- "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1"
},
"funding": [
{
@@ -1193,20 +1020,20 @@
"type": "tidelift"
}
],
- "time": "2025-02-12T12:17:51+00:00"
+ "time": "2025-04-29T12:36:36+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v5.4.0",
+ "version": "v5.5.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "447a020a1f875a434d62f2a401f53b82a396e494"
+ "reference": "ae59794362fe85e051a58ad36b289443f57be7a9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494",
- "reference": "447a020a1f875a434d62f2a401f53b82a396e494",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9",
+ "reference": "ae59794362fe85e051a58ad36b289443f57be7a9",
"shasum": ""
},
"require": {
@@ -1249,9 +1076,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0"
},
- "time": "2024-12-30T11:07:19+00:00"
+ "time": "2025-05-31T08:24:38+00:00"
},
{
"name": "phar-io/manifest",
@@ -1373,16 +1200,16 @@
},
{
"name": "phpstan/phpstan",
- "version": "2.1.11",
+ "version": "2.1.17",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "8ca5f79a8f63c49b2359065832a654e1ec70ac30"
+ "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8ca5f79a8f63c49b2359065832a654e1ec70ac30",
- "reference": "8ca5f79a8f63c49b2359065832a654e1ec70ac30",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053",
+ "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053",
"shasum": ""
},
"require": {
@@ -1427,7 +1254,7 @@
"type": "github"
}
],
- "time": "2025-03-24T13:45:00+00:00"
+ "time": "2025-05-21T20:55:28+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
@@ -1484,16 +1311,16 @@
},
{
"name": "phpstan/phpstan-strict-rules",
- "version": "2.0.4",
+ "version": "2.0.6",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
- "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a"
+ "reference": "f9f77efa9de31992a832ff77ea52eb42d675b094"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/3e139cbe67fafa3588e1dbe27ca50f31fdb6236a",
- "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a",
+ "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/f9f77efa9de31992a832ff77ea52eb42d675b094",
+ "reference": "f9f77efa9de31992a832ff77ea52eb42d675b094",
"shasum": ""
},
"require": {
@@ -1526,41 +1353,40 @@
"description": "Extra strict and opinionated rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
- "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.4"
+ "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.6"
},
- "time": "2025-03-18T11:42:40+00:00"
+ "time": "2025-07-21T12:19:29+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "10.1.16",
+ "version": "12.3.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "7e308268858ed6baedc8704a304727d20bc07c77"
+ "reference": "9075a8efc66e11bc55c319062e147bdb06777267"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77",
- "reference": "7e308268858ed6baedc8704a304727d20bc07c77",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9075a8efc66e11bc55c319062e147bdb06777267",
+ "reference": "9075a8efc66e11bc55c319062e147bdb06777267",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
- "nikic/php-parser": "^4.19.1 || ^5.1.0",
- "php": ">=8.1",
- "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",
+ "nikic/php-parser": "^5.4.0",
+ "php": ">=8.3",
+ "phpunit/php-file-iterator": "^6.0",
+ "phpunit/php-text-template": "^5.0",
+ "sebastian/complexity": "^5.0",
+ "sebastian/environment": "^8.0",
+ "sebastian/lines-of-code": "^4.0",
+ "sebastian/version": "^6.0",
"theseer/tokenizer": "^1.2.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.1"
+ "phpunit/phpunit": "^12.1"
},
"suggest": {
"ext-pcov": "PHP extension that provides line coverage",
@@ -1569,7 +1395,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "10.1.x-dev"
+ "dev-main": "12.3.x-dev"
}
},
"autoload": {
@@ -1598,40 +1424,52 @@
"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.16"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage",
+ "type": "tidelift"
}
],
- "time": "2024-08-22T04:31:57+00:00"
+ "time": "2025-05-23T15:49:03+00:00"
},
{
"name": "phpunit/php-file-iterator",
- "version": "4.1.0",
+ "version": "6.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c"
+ "reference": "961bc913d42fe24a257bfff826a5068079ac7782"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c",
- "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/961bc913d42fe24a257bfff826a5068079ac7782",
+ "reference": "961bc913d42fe24a257bfff826a5068079ac7782",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "4.0-dev"
+ "dev-main": "6.0-dev"
}
},
"autoload": {
@@ -1659,7 +1497,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
- "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0"
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.0"
},
"funding": [
{
@@ -1667,28 +1505,28 @@
"type": "github"
}
],
- "time": "2023-08-31T06:24:48+00:00"
+ "time": "2025-02-07T04:58:37+00:00"
},
{
"name": "phpunit/php-invoker",
- "version": "4.0.0",
+ "version": "6.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
- "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7"
+ "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7",
- "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/12b54e689b07a25a9b41e57736dfab6ec9ae5406",
+ "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
"ext-pcntl": "*",
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"suggest": {
"ext-pcntl": "*"
@@ -1696,7 +1534,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "4.0-dev"
+ "dev-main": "6.0-dev"
}
},
"autoload": {
@@ -1722,7 +1560,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
- "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0"
+ "security": "https://github.com/sebastianbergmann/php-invoker/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0"
},
"funding": [
{
@@ -1730,32 +1569,32 @@
"type": "github"
}
],
- "time": "2023-02-03T06:56:09+00:00"
+ "time": "2025-02-07T04:58:58+00:00"
},
{
"name": "phpunit/php-text-template",
- "version": "3.0.1",
+ "version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
- "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748"
+ "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748",
- "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/e1367a453f0eda562eedb4f659e13aa900d66c53",
+ "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.0-dev"
+ "dev-main": "5.0-dev"
}
},
"autoload": {
@@ -1782,7 +1621,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
"security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
- "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1"
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.0"
},
"funding": [
{
@@ -1790,32 +1629,32 @@
"type": "github"
}
],
- "time": "2023-08-31T14:07:24+00:00"
+ "time": "2025-02-07T04:59:16+00:00"
},
{
"name": "phpunit/php-timer",
- "version": "6.0.0",
+ "version": "8.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d"
+ "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d",
- "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc",
+ "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "6.0-dev"
+ "dev-main": "8.0-dev"
}
},
"autoload": {
@@ -1841,7 +1680,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
- "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0"
+ "security": "https://github.com/sebastianbergmann/php-timer/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0"
},
"funding": [
{
@@ -1849,20 +1689,20 @@
"type": "github"
}
],
- "time": "2023-02-03T06:57:52+00:00"
+ "time": "2025-02-07T04:59:38+00:00"
},
{
"name": "phpunit/phpunit",
- "version": "10.5.45",
+ "version": "12.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "bd68a781d8e30348bc297449f5234b3458267ae8"
+ "reference": "5f09fda04e7caea93cff50b4e90319184f3e6ee3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bd68a781d8e30348bc297449f5234b3458267ae8",
- "reference": "bd68a781d8e30348bc297449f5234b3458267ae8",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5f09fda04e7caea93cff50b4e90319184f3e6ee3",
+ "reference": "5f09fda04e7caea93cff50b4e90319184f3e6ee3",
"shasum": ""
},
"require": {
@@ -1872,29 +1712,25 @@
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
- "myclabs/deep-copy": "^1.12.1",
+ "myclabs/deep-copy": "^1.13.1",
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
- "php": ">=8.1",
- "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"
+ "php": ">=8.3",
+ "phpunit/php-code-coverage": "^12.3.0",
+ "phpunit/php-file-iterator": "^6.0.0",
+ "phpunit/php-invoker": "^6.0.0",
+ "phpunit/php-text-template": "^5.0.0",
+ "phpunit/php-timer": "^8.0.0",
+ "sebastian/cli-parser": "^4.0.0",
+ "sebastian/comparator": "^7.0.1",
+ "sebastian/diff": "^7.0.0",
+ "sebastian/environment": "^8.0.2",
+ "sebastian/exporter": "^7.0.0",
+ "sebastian/global-state": "^8.0.0",
+ "sebastian/object-enumerator": "^7.0.0",
+ "sebastian/type": "^6.0.2",
+ "sebastian/version": "^6.0.0",
+ "staabm/side-effects-detector": "^1.0.5"
},
"bin": [
"phpunit"
@@ -1902,7 +1738,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "10.5-dev"
+ "dev-main": "12.2-dev"
}
},
"autoload": {
@@ -1934,7 +1770,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.45"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/12.2.1"
},
"funding": [
{
@@ -1945,37 +1781,45 @@
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
- "time": "2025-02-06T16:08:12+00:00"
+ "time": "2025-06-07T05:17:47+00:00"
},
{
"name": "sebastian/cli-parser",
- "version": "2.0.1",
+ "version": "4.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
- "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084"
+ "reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084",
- "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/6d584c727d9114bcdc14c86711cd1cad51778e7c",
+ "reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "2.0-dev"
+ "dev-main": "4.0-dev"
}
},
"autoload": {
@@ -1999,7 +1843,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
- "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1"
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.0.0"
},
"funding": [
{
@@ -2007,147 +1851,39 @@
"type": "github"
}
],
- "time": "2024-03-02T07:12:49+00:00"
- },
- {
- "name": "sebastian/code-unit",
- "version": "2.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/code-unit.git",
- "reference": "a81fee9eef0b7a76af11d121767abc44c104e503"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503",
- "reference": "a81fee9eef0b7a76af11d121767abc44c104e503",
- "shasum": ""
- },
- "require": {
- "php": ">=8.1"
- },
- "require-dev": {
- "phpunit/phpunit": "^10.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "2.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Collection of value objects that represent the PHP code units",
- "homepage": "https://github.com/sebastianbergmann/code-unit",
- "support": {
- "issues": "https://github.com/sebastianbergmann/code-unit/issues",
- "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2023-02-03T06:58:43+00:00"
- },
- {
- "name": "sebastian/code-unit-reverse-lookup",
- "version": "3.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
- "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d",
- "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d",
- "shasum": ""
- },
- "require": {
- "php": ">=8.1"
- },
- "require-dev": {
- "phpunit/phpunit": "^10.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "3.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Looks up which function or method a line of code belongs to",
- "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
- "support": {
- "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
- "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2023-02-03T06:59:15+00:00"
+ "time": "2025-02-07T04:53:50+00:00"
},
{
"name": "sebastian/comparator",
- "version": "5.0.3",
+ "version": "7.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e"
+ "reference": "b478f34614f934e0291598d0c08cbaba9644bee5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e",
- "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/b478f34614f934e0291598d0c08cbaba9644bee5",
+ "reference": "b478f34614f934e0291598d0c08cbaba9644bee5",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-mbstring": "*",
- "php": ">=8.1",
- "sebastian/diff": "^5.0",
- "sebastian/exporter": "^5.0"
+ "php": ">=8.3",
+ "sebastian/diff": "^7.0",
+ "sebastian/exporter": "^7.0"
},
"require-dev": {
- "phpunit/phpunit": "^10.5"
+ "phpunit/phpunit": "^12.0"
+ },
+ "suggest": {
+ "ext-bcmath": "For comparing BcMath\\Number objects"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "5.0-dev"
+ "dev-main": "7.0-dev"
}
},
"autoload": {
@@ -2187,7 +1923,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.3"
+ "source": "https://github.com/sebastianbergmann/comparator/tree/7.0.1"
},
"funding": [
{
@@ -2195,33 +1931,33 @@
"type": "github"
}
],
- "time": "2024-10-18T14:56:07+00:00"
+ "time": "2025-03-07T07:00:32+00:00"
},
{
"name": "sebastian/complexity",
- "version": "3.2.0",
+ "version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
- "reference": "68ff824baeae169ec9f2137158ee529584553799"
+ "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799",
- "reference": "68ff824baeae169ec9f2137158ee529584553799",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/bad4316aba5303d0221f43f8cee37eb58d384bbb",
+ "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb",
"shasum": ""
},
"require": {
- "nikic/php-parser": "^4.18 || ^5.0",
- "php": ">=8.1"
+ "nikic/php-parser": "^5.0",
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.2-dev"
+ "dev-main": "5.0-dev"
}
},
"autoload": {
@@ -2245,7 +1981,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"security": "https://github.com/sebastianbergmann/complexity/security/policy",
- "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0"
+ "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0"
},
"funding": [
{
@@ -2253,33 +1989,33 @@
"type": "github"
}
],
- "time": "2023-12-21T08:37:17+00:00"
+ "time": "2025-02-07T04:55:25+00:00"
},
{
"name": "sebastian/diff",
- "version": "5.1.1",
+ "version": "7.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e"
+ "reference": "7ab1ea946c012266ca32390913653d844ecd085f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e",
- "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f",
+ "reference": "7ab1ea946c012266ca32390913653d844ecd085f",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0",
- "symfony/process": "^6.4"
+ "phpunit/phpunit": "^12.0",
+ "symfony/process": "^7.2"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "5.1-dev"
+ "dev-main": "7.0-dev"
}
},
"autoload": {
@@ -2312,7 +2048,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"security": "https://github.com/sebastianbergmann/diff/security/policy",
- "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1"
+ "source": "https://github.com/sebastianbergmann/diff/tree/7.0.0"
},
"funding": [
{
@@ -2320,27 +2056,27 @@
"type": "github"
}
],
- "time": "2024-03-02T07:15:17+00:00"
+ "time": "2025-02-07T04:55:46+00:00"
},
{
"name": "sebastian/environment",
- "version": "6.1.0",
+ "version": "8.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "8074dbcd93529b357029f5cc5058fd3e43666984"
+ "reference": "d364b9e5d0d3b18a2573351a1786fbf96b7e0792"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984",
- "reference": "8074dbcd93529b357029f5cc5058fd3e43666984",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d364b9e5d0d3b18a2573351a1786fbf96b7e0792",
+ "reference": "d364b9e5d0d3b18a2573351a1786fbf96b7e0792",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"suggest": {
"ext-posix": "*"
@@ -2348,7 +2084,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "6.1-dev"
+ "dev-main": "8.0-dev"
}
},
"autoload": {
@@ -2376,42 +2112,54 @@
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
"security": "https://github.com/sebastianbergmann/environment/security/policy",
- "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0"
+ "source": "https://github.com/sebastianbergmann/environment/tree/8.0.2"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/environment",
+ "type": "tidelift"
}
],
- "time": "2024-03-23T08:47:14+00:00"
+ "time": "2025-05-21T15:05:44+00:00"
},
{
"name": "sebastian/exporter",
- "version": "5.1.2",
+ "version": "7.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "955288482d97c19a372d3f31006ab3f37da47adf"
+ "reference": "76432aafc58d50691a00d86d0632f1217a47b688"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf",
- "reference": "955288482d97c19a372d3f31006ab3f37da47adf",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/76432aafc58d50691a00d86d0632f1217a47b688",
+ "reference": "76432aafc58d50691a00d86d0632f1217a47b688",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
- "php": ">=8.1",
- "sebastian/recursion-context": "^5.0"
+ "php": ">=8.3",
+ "sebastian/recursion-context": "^7.0"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "5.1-dev"
+ "dev-main": "7.0-dev"
}
},
"autoload": {
@@ -2454,7 +2202,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
"security": "https://github.com/sebastianbergmann/exporter/security/policy",
- "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2"
+ "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.0"
},
"funding": [
{
@@ -2462,35 +2210,35 @@
"type": "github"
}
],
- "time": "2024-03-02T07:17:12+00:00"
+ "time": "2025-02-07T04:56:42+00:00"
},
{
"name": "sebastian/global-state",
- "version": "6.0.2",
+ "version": "8.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9"
+ "reference": "570a2aeb26d40f057af686d63c4e99b075fb6cbc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
- "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/570a2aeb26d40f057af686d63c4e99b075fb6cbc",
+ "reference": "570a2aeb26d40f057af686d63c4e99b075fb6cbc",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "sebastian/object-reflector": "^3.0",
- "sebastian/recursion-context": "^5.0"
+ "php": ">=8.3",
+ "sebastian/object-reflector": "^5.0",
+ "sebastian/recursion-context": "^7.0"
},
"require-dev": {
"ext-dom": "*",
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "6.0-dev"
+ "dev-main": "8.0-dev"
}
},
"autoload": {
@@ -2516,7 +2264,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"security": "https://github.com/sebastianbergmann/global-state/security/policy",
- "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2"
+ "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.0"
},
"funding": [
{
@@ -2524,33 +2272,33 @@
"type": "github"
}
],
- "time": "2024-03-02T07:19:19+00:00"
+ "time": "2025-02-07T04:56:59+00:00"
},
{
"name": "sebastian/lines-of-code",
- "version": "2.0.2",
+ "version": "4.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
- "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0"
+ "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0",
- "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/97ffee3bcfb5805568d6af7f0f893678fc076d2f",
+ "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f",
"shasum": ""
},
"require": {
- "nikic/php-parser": "^4.18 || ^5.0",
- "php": ">=8.1"
+ "nikic/php-parser": "^5.0",
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "2.0-dev"
+ "dev-main": "4.0-dev"
}
},
"autoload": {
@@ -2574,7 +2322,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
- "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2"
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.0"
},
"funding": [
{
@@ -2582,34 +2330,34 @@
"type": "github"
}
],
- "time": "2023-12-21T08:38:20+00:00"
+ "time": "2025-02-07T04:57:28+00:00"
},
{
"name": "sebastian/object-enumerator",
- "version": "5.0.0",
+ "version": "7.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
- "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906"
+ "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906",
- "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1effe8e9b8e068e9ae228e542d5d11b5d16db894",
+ "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "sebastian/object-reflector": "^3.0",
- "sebastian/recursion-context": "^5.0"
+ "php": ">=8.3",
+ "sebastian/object-reflector": "^5.0",
+ "sebastian/recursion-context": "^7.0"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "5.0-dev"
+ "dev-main": "7.0-dev"
}
},
"autoload": {
@@ -2631,7 +2379,8 @@
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
- "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0"
+ "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy",
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0"
},
"funding": [
{
@@ -2639,32 +2388,32 @@
"type": "github"
}
],
- "time": "2023-02-03T07:08:32+00:00"
+ "time": "2025-02-07T04:57:48+00:00"
},
{
"name": "sebastian/object-reflector",
- "version": "3.0.0",
+ "version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
- "reference": "24ed13d98130f0e7122df55d06c5c4942a577957"
+ "reference": "4bfa827c969c98be1e527abd576533293c634f6a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957",
- "reference": "24ed13d98130f0e7122df55d06c5c4942a577957",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/4bfa827c969c98be1e527abd576533293c634f6a",
+ "reference": "4bfa827c969c98be1e527abd576533293c634f6a",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.0-dev"
+ "dev-main": "5.0-dev"
}
},
"autoload": {
@@ -2686,7 +2435,8 @@
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
- "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0"
+ "security": "https://github.com/sebastianbergmann/object-reflector/security/policy",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0"
},
"funding": [
{
@@ -2694,32 +2444,32 @@
"type": "github"
}
],
- "time": "2023-02-03T07:06:18+00:00"
+ "time": "2025-02-07T04:58:17+00:00"
},
{
"name": "sebastian/recursion-context",
- "version": "5.0.0",
+ "version": "7.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "05909fb5bc7df4c52992396d0116aed689f93712"
+ "reference": "c405ae3a63e01b32eb71577f8ec1604e39858a7c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712",
- "reference": "05909fb5bc7df4c52992396d0116aed689f93712",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/c405ae3a63e01b32eb71577f8ec1604e39858a7c",
+ "reference": "c405ae3a63e01b32eb71577f8ec1604e39858a7c",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "5.0-dev"
+ "dev-main": "7.0-dev"
}
},
"autoload": {
@@ -2749,7 +2499,8 @@
"homepage": "https://github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
- "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0"
+ "security": "https://github.com/sebastianbergmann/recursion-context/security/policy",
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.0"
},
"funding": [
{
@@ -2757,32 +2508,32 @@
"type": "github"
}
],
- "time": "2023-02-03T07:05:40+00:00"
+ "time": "2025-02-07T05:00:01+00:00"
},
{
"name": "sebastian/type",
- "version": "4.0.0",
+ "version": "6.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
- "reference": "462699a16464c3944eefc02ebdd77882bd3925bf"
+ "reference": "1d7cd6e514384c36d7a390347f57c385d4be6069"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf",
- "reference": "462699a16464c3944eefc02ebdd77882bd3925bf",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/1d7cd6e514384c36d7a390347f57c385d4be6069",
+ "reference": "1d7cd6e514384c36d7a390347f57c385d4be6069",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^12.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "4.0-dev"
+ "dev-main": "6.0-dev"
}
},
"autoload": {
@@ -2805,7 +2556,8 @@
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
- "source": "https://github.com/sebastianbergmann/type/tree/4.0.0"
+ "security": "https://github.com/sebastianbergmann/type/security/policy",
+ "source": "https://github.com/sebastianbergmann/type/tree/6.0.2"
},
"funding": [
{
@@ -2813,29 +2565,29 @@
"type": "github"
}
],
- "time": "2023-02-03T07:10:45+00:00"
+ "time": "2025-03-18T13:37:31+00:00"
},
{
"name": "sebastian/version",
- "version": "4.0.1",
+ "version": "6.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
- "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17"
+ "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17",
- "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/3e6ccf7657d4f0a59200564b08cead899313b53c",
+ "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "4.0-dev"
+ "dev-main": "6.0-dev"
}
},
"autoload": {
@@ -2858,7 +2610,8 @@
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
- "source": "https://github.com/sebastianbergmann/version/tree/4.0.1"
+ "security": "https://github.com/sebastianbergmann/version/security/policy",
+ "source": "https://github.com/sebastianbergmann/version/tree/6.0.0"
},
"funding": [
{
@@ -2866,7 +2619,59 @@
"type": "github"
}
],
- "time": "2023-02-07T11:34:05+00:00"
+ "time": "2025-02-07T05:00:38+00:00"
+ },
+ {
+ "name": "staabm/side-effects-detector",
+ "version": "1.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/staabm/side-effects-detector.git",
+ "reference": "d8334211a140ce329c13726d4a715adbddd0a163"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163",
+ "reference": "d8334211a140ce329c13726d4a715adbddd0a163",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^1.12.6",
+ "phpunit/phpunit": "^9.6.21",
+ "symfony/var-dumper": "^5.4.43",
+ "tomasvotruba/type-coverage": "1.0.0",
+ "tomasvotruba/unused-public": "1.0.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "lib/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A static analysis tool to detect side effects in PHP code",
+ "keywords": [
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/staabm/side-effects-detector/issues",
+ "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/staabm",
+ "type": "github"
+ }
+ ],
+ "time": "2024-10-20T05:08:20+00:00"
},
{
"name": "theseer/tokenizer",
@@ -2919,13 +2724,23 @@
"time": "2024-03-03T12:36:25+00:00"
}
],
- "aliases": [],
+ "aliases": [
+ {
+ "package": "pocketmine/math",
+ "version": "dev-major-next",
+ "alias": "1.0.0",
+ "alias_normalized": "1.0.0.0"
+ }
+ ],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {
+ "pocketmine/callback-validator": 20,
+ "pocketmine/math": 20
+ },
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": "^8.1",
+ "php": "^8.3",
"php-64bit": "*",
"ext-chunkutils2": "^0.3.1",
"ext-crypto": "^0.3.1",
@@ -2952,9 +2767,9 @@
"ext-zlib": ">=1.2.11",
"composer-runtime-api": "^2.0"
},
- "platform-dev": [],
+ "platform-dev": {},
"platform-overrides": {
- "php": "8.1.0"
+ "php": "8.3.0"
},
"plugin-api-version": "2.6.0"
}
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 4ac7b4410..5bbbf982b 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -13,7 +13,7 @@ rules:
- pocketmine\phpstan\rules\DisallowDynamicNewRule
- pocketmine\phpstan\rules\DisallowForeachByReferenceRule
- pocketmine\phpstan\rules\ExplodeLimitRule
- - pocketmine\phpstan\rules\UnsafeForeachArrayOfStringRule
+ - pocketmine\phpstan\rules\UnsafeForeachRule
# - pocketmine\phpstan\rules\ThreadedSupportedTypesRule
parameters:
diff --git a/src/PocketMine.php b/src/PocketMine.php
index a71c9768d..04b95dd32 100644
--- a/src/PocketMine.php
+++ b/src/PocketMine.php
@@ -55,7 +55,7 @@ namespace pocketmine {
require_once __DIR__ . '/VersionInfo.php';
- const MIN_PHP_VERSION = "8.1.0";
+ const MIN_PHP_VERSION = "8.3.0";
/**
* @param string $message
diff --git a/src/Server.php b/src/Server.php
index 0d58bd579..a3b00f461 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -1624,7 +1624,7 @@ class Server{
if(!is_dir($crashFolder)){
mkdir($crashFolder);
}
- $crashDumpPath = Path::join($crashFolder, date("D_M_j-H.i.s-T_Y", (int) $dump->getData()->time) . ".log");
+ $crashDumpPath = Path::join($crashFolder, date("Y-m-d_H.i.s_T", (int) $dump->getData()->time) . ".log");
$fp = @fopen($crashDumpPath, "wb");
if(!is_resource($fp)){
diff --git a/src/VersionInfo.php b/src/VersionInfo.php
index 44238dba3..1d4179f7d 100644
--- a/src/VersionInfo.php
+++ b/src/VersionInfo.php
@@ -31,7 +31,7 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
- public const BASE_VERSION = "5.27.2";
+ public const BASE_VERSION = "5.33.1";
public const IS_DEVELOPMENT_BUILD = true;
public const BUILD_CHANNEL = "stable";
diff --git a/src/block/ActivatorRail.php b/src/block/ActivatorRail.php
index dcd0ef93b..da15eb1e8 100644
--- a/src/block/ActivatorRail.php
+++ b/src/block/ActivatorRail.php
@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\PoweredByRedstone;
use pocketmine\block\utils\RailPoweredByRedstoneTrait;
-class ActivatorRail extends StraightOnlyRail{
+class ActivatorRail extends StraightOnlyRail implements PoweredByRedstone{
use RailPoweredByRedstoneTrait;
//TODO
diff --git a/src/block/AmethystCluster.php b/src/block/AmethystCluster.php
index 639490456..d939994a2 100644
--- a/src/block/AmethystCluster.php
+++ b/src/block/AmethystCluster.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\AmethystTrait;
+use pocketmine\block\utils\AnyFacing;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\block\utils\SupportType;
@@ -38,7 +39,7 @@ use pocketmine\player\Player;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\BlockTransaction;
-final class AmethystCluster extends Transparent{
+final class AmethystCluster extends Transparent implements AnyFacing{
use AmethystTrait;
use AnyFacingTrait;
@@ -81,22 +82,22 @@ final class AmethystCluster extends Transparent{
if($axis === $myAxis){
continue;
}
- $box->squash($axis, $this->stage === self::STAGE_SMALL_BUD ? 4 / 16 : 3 / 16);
+ $box = $box->squashedCopy($axis, $this->stage === self::STAGE_SMALL_BUD ? 4 / 16 : 3 / 16);
}
- $box->trim($this->facing, 1 - ($this->stage === self::STAGE_CLUSTER ? 7 / 16 : ($this->stage + 3) / 16));
+ $box = $box->trimmedCopy($this->facing, 1 - ($this->stage === self::STAGE_CLUSTER ? 7 / 16 : ($this->stage + 3) / 16));
return [$box];
}
- private function canBeSupportedAt(Block $block, int $facing) : bool{
+ private function canBeSupportedAt(Block $block, Facing $facing) : bool{
return $block->getAdjacentSupportType($facing) === SupportType::FULL;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
diff --git a/src/block/Anvil.php b/src/block/Anvil.php
index c98f20b5e..dc9a75a18 100644
--- a/src/block/Anvil.php
+++ b/src/block/Anvil.php
@@ -26,6 +26,8 @@ namespace pocketmine\block;
use pocketmine\block\inventory\window\AnvilInventoryWindow;
use pocketmine\block\utils\Fallable;
use pocketmine\block\utils\FallableTrait;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -41,7 +43,7 @@ use pocketmine\world\sound\AnvilFallSound;
use pocketmine\world\sound\Sound;
use function round;
-class Anvil extends Transparent implements Fallable{
+class Anvil extends Transparent implements Fallable, HorizontalFacing{
use FallableTrait;
use HorizontalFacingTrait;
@@ -56,7 +58,7 @@ class Anvil extends Transparent implements Fallable{
}
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
}
public function getDamage() : int{ return $this->damage; }
@@ -71,14 +73,14 @@ class Anvil extends Transparent implements Fallable{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->squash(Facing::axis(Facing::rotateY($this->facing, false)), 1 / 8)];
+ return [AxisAlignedBB::one()->squashedCopy(Facing::axis(Facing::rotateY($this->facing->toFacing(), false)), 1 / 8)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
$player->setCurrentWindow(new AnvilInventoryWindow($player, $this->position));
}
@@ -86,9 +88,9 @@ class Anvil extends Transparent implements Fallable{
return true;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
- $this->facing = Facing::rotateY($player->getHorizontalFacing(), false);
+ $this->facing = HorizontalFacingOption::fromFacing(Facing::rotateY($player->getHorizontalFacing(), false));
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
diff --git a/src/block/Bamboo.php b/src/block/Bamboo.php
index fd64e10ef..015db6a18 100644
--- a/src/block/Bamboo.php
+++ b/src/block/Bamboo.php
@@ -90,10 +90,10 @@ class Bamboo extends Transparent{
protected function recalculateCollisionBoxes() : array{
//this places the BB at the northwest corner, not the center
$inset = 1 - (($this->thick ? 3 : 2) / 16);
- return [AxisAlignedBB::one()->trim(Facing::SOUTH, $inset)->trim(Facing::EAST, $inset)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::SOUTH, $inset)->trimmedCopy(Facing::EAST, $inset)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -138,7 +138,7 @@ class Bamboo extends Transparent{
return $top;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer){
$top = $this->seekToTop();
if($top->grow(self::getMaxHeight($top->position->getFloorX(), $top->position->getFloorZ()), mt_rand(1, 2), $player)){
diff --git a/src/block/BambooSapling.php b/src/block/BambooSapling.php
index 67c8a24e0..ddcde9981 100644
--- a/src/block/BambooSapling.php
+++ b/src/block/BambooSapling.php
@@ -61,7 +61,7 @@ final class BambooSapling extends Flowable{
$supportBlock->hasTypeTag(BlockTypeTags::SAND);
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer || $item instanceof ItemBamboo){
if($this->grow($player)){
$item->pop();
diff --git a/src/block/Barrel.php b/src/block/Barrel.php
index 1b64e814c..b17c583e8 100644
--- a/src/block/Barrel.php
+++ b/src/block/Barrel.php
@@ -27,6 +27,7 @@ use pocketmine\block\inventory\window\BlockInventoryWindow;
use pocketmine\block\tile\Barrel as TileBarrel;
use pocketmine\block\utils\AnimatedContainer;
use pocketmine\block\utils\AnimatedContainerTrait;
+use pocketmine\block\utils\AnyFacing;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
@@ -40,14 +41,14 @@ use pocketmine\world\sound\BarrelOpenSound;
use pocketmine\world\sound\Sound;
use function abs;
-class Barrel extends Opaque implements AnimatedContainer{
+class Barrel extends Opaque implements AnimatedContainer, AnyFacing{
use AnimatedContainerTrait;
use AnyFacingTrait;
protected bool $open = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->facing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->open);
}
@@ -61,7 +62,7 @@ class Barrel extends Opaque implements AnimatedContainer{
return $this;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
if(abs($player->getPosition()->x - $this->position->x) < 2 && abs($player->getPosition()->z - $this->position->z) < 2){
$y = $player->getEyePos()->y;
@@ -81,7 +82,7 @@ class Barrel extends Opaque implements AnimatedContainer{
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{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
$barrel = $this->position->getWorld()->getTile($this->position);
if($barrel instanceof TileBarrel){
diff --git a/src/block/BaseBanner.php b/src/block/BaseBanner.php
index b56323453..dcdc36c60 100644
--- a/src/block/BaseBanner.php
+++ b/src/block/BaseBanner.php
@@ -25,18 +25,20 @@ namespace pocketmine\block;
use pocketmine\block\tile\Banner as TileBanner;
use pocketmine\block\utils\BannerPatternLayer;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Banner as ItemBanner;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use function assert;
use function count;
-abstract class BaseBanner extends Transparent{
+abstract class BaseBanner extends Transparent implements Colored{
use ColoredTrait;
/**
@@ -49,6 +51,10 @@ abstract class BaseBanner extends Transparent{
parent::readStateFromWorld();
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileBanner){
+ if($tile->getType() === TileBanner::TYPE_OMINOUS){
+ //illager banner is implemented as a separate block, as it doesn't support base color or custom patterns
+ return $this->getOminousVersion();
+ }
$this->color = $tile->getBaseColor();
$this->setPatterns($tile->getPatterns());
}
@@ -56,6 +62,13 @@ abstract class BaseBanner extends Transparent{
return $this;
}
+ /**
+ * TODO: make this abstract in PM6 (BC break)
+ */
+ protected function getOminousVersion() : Block{
+ return VanillaBlocks::AIR();
+ }
+
public function writeStateToWorld() : void{
parent::writeStateToWorld();
$tile = $this->position->getWorld()->getTile($this->position);
@@ -100,7 +113,7 @@ abstract class BaseBanner extends Transparent{
return [];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -108,7 +121,7 @@ abstract class BaseBanner extends Transparent{
return $block->isSolid();
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide($this->getSupportingFace()))){
return false;
}
@@ -120,7 +133,7 @@ abstract class BaseBanner extends Transparent{
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
- abstract protected function getSupportingFace() : int;
+ abstract protected function getSupportingFace() : Facing;
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide($this->getSupportingFace()))){
diff --git a/src/block/BaseBigDripleaf.php b/src/block/BaseBigDripleaf.php
index f0ff59cf0..c94300959 100644
--- a/src/block/BaseBigDripleaf.php
+++ b/src/block/BaseBigDripleaf.php
@@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\StructureGrowEvent;
@@ -33,7 +35,7 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-abstract class BaseBigDripleaf extends Transparent{
+abstract class BaseBigDripleaf extends Transparent implements HorizontalFacing{
use HorizontalFacingTrait;
abstract protected function isHead() : bool;
@@ -56,13 +58,13 @@ abstract class BaseBigDripleaf extends Transparent{
}
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$block = $blockReplace->getSide(Facing::DOWN);
if(!$this->canBeSupportedBy($block, true)){
return false;
}
if($player !== null){
- $this->facing = Facing::opposite($player->getHorizontalFacing());
+ $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
}
if($block instanceof BaseBigDripleaf){
$this->facing = $block->facing;
@@ -71,7 +73,7 @@ abstract class BaseBigDripleaf extends Transparent{
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{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
return true;
@@ -130,7 +132,7 @@ abstract class BaseBigDripleaf extends Transparent{
return 100;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
}
diff --git a/src/block/BaseCake.php b/src/block/BaseCake.php
index 4b3903840..47a5f60f9 100644
--- a/src/block/BaseCake.php
+++ b/src/block/BaseCake.php
@@ -36,7 +36,7 @@ use pocketmine\player\Player;
abstract class BaseCake extends Transparent implements FoodSource{
use StaticSupportTrait;
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -44,7 +44,7 @@ abstract class BaseCake extends Transparent implements FoodSource{
return $block->getSide(Facing::DOWN)->getTypeId() !== BlockTypeIds::AIR;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){
return $player->consumeObject($this);
}
diff --git a/src/block/BaseCoral.php b/src/block/BaseCoral.php
index b9c595a97..936d068ed 100644
--- a/src/block/BaseCoral.php
+++ b/src/block/BaseCoral.php
@@ -24,12 +24,14 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
+use pocketmine\block\utils\CoralMaterial;
use pocketmine\block\utils\CoralTypeTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use function mt_rand;
-abstract class BaseCoral extends Transparent{
+abstract class BaseCoral extends Transparent implements CoralMaterial{
use CoralTypeTrait;
public function onNearbyBlockChange() : void{
@@ -71,7 +73,7 @@ abstract class BaseCoral extends Transparent{
protected function recalculateCollisionBoxes() : array{ return []; }
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
}
diff --git a/src/block/BaseOminousBanner.php b/src/block/BaseOminousBanner.php
new file mode 100644
index 000000000..a16e133a7
--- /dev/null
+++ b/src/block/BaseOminousBanner.php
@@ -0,0 +1,91 @@
+position->getWorld()->getTile($this->position);
+ assert($tile instanceof TileBanner);
+ $tile->setBaseColor(DyeColor::WHITE);
+ $tile->setPatterns([]);
+ $tile->setType(TileBanner::TYPE_OMINOUS);
+ }
+
+ public function isSolid() : bool{
+ return false;
+ }
+
+ public function getMaxStackSize() : int{
+ return 16;
+ }
+
+ public function getFuelTime() : int{
+ return 300;
+ }
+
+ protected function recalculateCollisionBoxes() : array{
+ return [];
+ }
+
+ public function getSupportType(Facing $facing) : SupportType{
+ return SupportType::NONE;
+ }
+
+ private function canBeSupportedBy(Block $block) : bool{
+ return $block->isSolid();
+ }
+
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ if(!$this->canBeSupportedBy($blockReplace->getSide($this->getSupportingFace()))){
+ return false;
+ }
+
+ return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
+ }
+
+ abstract protected function getSupportingFace() : Facing;
+
+ public function onNearbyBlockChange() : void{
+ if(!$this->canBeSupportedBy($this->getSide($this->getSupportingFace()))){
+ $this->position->getWorld()->useBreakOn($this->position);
+ }
+ }
+
+ public function asItem() : Item{
+ return VanillaItems::OMINOUS_BANNER();
+ }
+}
diff --git a/src/block/BaseRail.php b/src/block/BaseRail.php
index 0bcb2f340..15b7d2bec 100644
--- a/src/block/BaseRail.php
+++ b/src/block/BaseRail.php
@@ -37,7 +37,7 @@ use function in_array;
abstract class BaseRail extends Flowable{
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockReplace->getAdjacentSupportType(Facing::DOWN)->hasEdgeSupport()){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@@ -89,8 +89,9 @@ abstract class BaseRail extends Flowable{
/** @var int $connection */
foreach($this->getCurrentShapeConnections() as $connection){
- $other = $this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND);
- $otherConnection = Facing::opposite($connection & ~RailConnectionInfo::FLAG_ASCEND);
+ $connectionFace = Facing::from($connection & ~RailConnectionInfo::FLAG_ASCEND);
+ $other = $this->getSide($connectionFace);
+ $otherConnection = Facing::opposite($connectionFace)->value;
if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0){
$other = $other->getSide(Facing::UP);
@@ -122,10 +123,10 @@ abstract class BaseRail extends Flowable{
case 0:
//No constraints, can connect in any direction
$possible = [
- Facing::NORTH => true,
- Facing::SOUTH => true,
- Facing::WEST => true,
- Facing::EAST => true
+ Facing::NORTH->value => true,
+ Facing::SOUTH->value => true,
+ Facing::WEST->value => true,
+ Facing::EAST->value => true
];
foreach($possible as $p => $_){
$possible[$p | RailConnectionInfo::FLAG_ASCEND] = true;
@@ -146,13 +147,13 @@ abstract class BaseRail extends Flowable{
* @phpstan-return array
*/
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
- $opposite = Facing::opposite($constraint & ~RailConnectionInfo::FLAG_ASCEND);
+ $opposite = Facing::opposite(Facing::from($constraint & ~RailConnectionInfo::FLAG_ASCEND));
- $possible = [$opposite => true];
+ $possible = [$opposite->value => true];
if(($constraint & RailConnectionInfo::FLAG_ASCEND) === 0){
//We can slope the other way if this connection isn't already a slope
- $possible[$opposite | RailConnectionInfo::FLAG_ASCEND] = true;
+ $possible[$opposite->value | RailConnectionInfo::FLAG_ASCEND] = true;
}
return $possible;
@@ -168,9 +169,10 @@ abstract class BaseRail extends Flowable{
$continue = false;
foreach($possible as $thisSide => $_){
- $otherSide = Facing::opposite($thisSide & ~RailConnectionInfo::FLAG_ASCEND);
+ $thisSideEnum = Facing::from($thisSide & ~RailConnectionInfo::FLAG_ASCEND);
+ $otherSide = Facing::opposite($thisSideEnum)->value;
- $other = $this->getSide($thisSide & ~RailConnectionInfo::FLAG_ASCEND);
+ $other = $this->getSide($thisSideEnum);
if(($thisSide & RailConnectionInfo::FLAG_ASCEND) !== 0){
$other = $other->getSide(Facing::UP);
@@ -212,7 +214,7 @@ abstract class BaseRail extends Flowable{
*/
private function setConnections(array $connections) : void{
if(count($connections) === 1){
- $connections[] = Facing::opposite($connections[0] & ~RailConnectionInfo::FLAG_ASCEND);
+ $connections[] = Facing::opposite(Facing::from($connections[0] & ~RailConnectionInfo::FLAG_ASCEND))->value;
}elseif(count($connections) !== 2){
throw new \InvalidArgumentException("Expected exactly 2 connections, got " . count($connections));
}
@@ -226,7 +228,7 @@ abstract class BaseRail extends Flowable{
$world->useBreakOn($this->position);
}else{
foreach($this->getCurrentShapeConnections() as $connection){
- if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0 && !$this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND)->getSupportType(Facing::UP)->hasEdgeSupport()){
+ if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0 && !$this->getSide(Facing::from($connection & ~RailConnectionInfo::FLAG_ASCEND))->getSupportType(Facing::UP)->hasEdgeSupport()){
$world->useBreakOn($this->position);
break;
}
diff --git a/src/block/BaseSign.php b/src/block/BaseSign.php
index 0f5d77d58..f631ff60a 100644
--- a/src/block/BaseSign.php
+++ b/src/block/BaseSign.php
@@ -27,6 +27,7 @@ use pocketmine\block\tile\Sign as TileSign;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\SignText;
use pocketmine\block\utils\SupportType;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodType;
use pocketmine\block\utils\WoodTypeTrait;
use pocketmine\color\Color;
@@ -34,6 +35,7 @@ use pocketmine\event\block\SignChangeEvent;
use pocketmine\item\Dye;
use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;
@@ -44,7 +46,7 @@ use function array_map;
use function assert;
use function strlen;
-abstract class BaseSign extends Transparent{
+abstract class BaseSign extends Transparent implements WoodMaterial{
use WoodTypeTrait;
protected SignText $text;
@@ -98,11 +100,11 @@ abstract class BaseSign extends Transparent{
return [];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
- abstract protected function getSupportingFace() : int;
+ abstract protected function getSupportingFace() : Facing;
public function onNearbyBlockChange() : void{
if($this->getSide($this->getSupportingFace())->getTypeId() === BlockTypeIds::AIR){
@@ -110,7 +112,7 @@ abstract class BaseSign extends Transparent{
}
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$this->editorEntityRuntimeId = $player->getId();
}
@@ -159,7 +161,7 @@ abstract class BaseSign extends Transparent{
return true;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player === null){
return false;
}
diff --git a/src/block/Bed.php b/src/block/Bed.php
index 133c4a9cc..8e7bf5a4a 100644
--- a/src/block/Bed.php
+++ b/src/block/Bed.php
@@ -24,8 +24,11 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\tile\Bed as TileBed;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\DyeColor;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -41,7 +44,7 @@ use pocketmine\utils\TextFormat;
use pocketmine\world\BlockTransaction;
use pocketmine\world\World;
-class Bed extends Transparent{
+class Bed extends Transparent implements Colored, HorizontalFacing{
use ColoredTrait;
use HorizontalFacingTrait;
@@ -49,7 +52,7 @@ class Bed extends Transparent{
protected bool $head = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->occupied);
$w->bool($this->head);
}
@@ -77,10 +80,10 @@ class Bed extends Transparent{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 16)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 7 / 16)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -104,8 +107,8 @@ class Bed extends Transparent{
return $this;
}
- private function getOtherHalfSide() : int{
- return $this->head ? Facing::opposite($this->facing) : $this->facing;
+ private function getOtherHalfSide() : Facing{
+ return $this->head ? Facing::opposite($this->facing->toFacing()) : $this->facing->toFacing();
}
public function getOtherHalf() : ?Bed{
@@ -117,7 +120,7 @@ class Bed extends Transparent{
return null;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){
$other = $this->getOtherHalf();
$playerPos = $player->getPosition();
@@ -170,9 +173,11 @@ class Bed extends Transparent{
return $entity->getMotion()->y * -3 / 4; // 2/3 in Java, according to the wiki
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedAt($blockReplace)){
- $this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH;
+ if($player !== null){
+ $this->facing = HorizontalFacingOption::fromFacing($player->getHorizontalFacing());
+ }
$next = $this->getSide($this->getOtherHalfSide());
if($next->canBeReplaced() && $this->canBeSupportedAt($next)){
diff --git a/src/block/Bell.php b/src/block/Bell.php
index 53a6fc7fb..976793720 100644
--- a/src/block/Bell.php
+++ b/src/block/Bell.php
@@ -25,6 +25,8 @@ namespace pocketmine\block;
use pocketmine\block\tile\Bell as TileBell;
use pocketmine\block\utils\BellAttachmentType;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -38,39 +40,40 @@ use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\BellRingSound;
-final class Bell extends Transparent{
+final class Bell extends Transparent implements HorizontalFacing{
use HorizontalFacingTrait;
private BellAttachmentType $attachmentType = BellAttachmentType::FLOOR;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->enum($this->attachmentType);
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
}
protected function recalculateCollisionBoxes() : array{
+ $realFacing = $this->facing->toFacing();
if($this->attachmentType === BellAttachmentType::FLOOR){
return [
- AxisAlignedBB::one()->squash(Facing::axis($this->facing), 1 / 4)->trim(Facing::UP, 3 / 16)
+ AxisAlignedBB::one()->squashedCopy(Facing::axis($realFacing), 1 / 4)->trimmedCopy(Facing::UP, 3 / 16)
];
}
if($this->attachmentType === BellAttachmentType::CEILING){
return [
- AxisAlignedBB::one()->contract(1 / 4, 0, 1 / 4)->trim(Facing::DOWN, 1 / 4)
+ AxisAlignedBB::one()->contractedCopy(1 / 4, 0, 1 / 4)->trimmedCopy(Facing::DOWN, 1 / 4)
];
}
$box = AxisAlignedBB::one()
- ->squash(Facing::axis(Facing::rotateY($this->facing, true)), 1 / 4)
- ->trim(Facing::UP, 1 / 16)
- ->trim(Facing::DOWN, 1 / 4);
+ ->squashedCopy(Facing::axis(Facing::rotateY($realFacing, true)), 1 / 4)
+ ->trimmedCopy(Facing::UP, 1 / 16)
+ ->trimmedCopy(Facing::DOWN, 1 / 4);
return [
- $this->attachmentType === BellAttachmentType::ONE_WALL ? $box->trim($this->facing, 3 / 16) : $box
+ $this->attachmentType === BellAttachmentType::ONE_WALL ? $box->trimmedCopy($realFacing, 3 / 16) : $box
];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -82,23 +85,23 @@ final class Bell extends Transparent{
return $this;
}
- private function canBeSupportedAt(Block $block, int $face) : bool{
+ private function canBeSupportedAt(Block $block, Facing $face) : bool{
return $block->getAdjacentSupportType($face) !== SupportType::NONE;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
if($face === Facing::UP){
if($player !== null){
- $this->setFacing(Facing::opposite($player->getHorizontalFacing()));
+ $this->setFacing(HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing())));
}
$this->setAttachmentType(BellAttachmentType::FLOOR);
}elseif($face === Facing::DOWN){
$this->setAttachmentType(BellAttachmentType::CEILING);
}else{
- $this->setFacing($face);
+ $this->setFacing(HorizontalFacingOption::fromFacing($face));
$this->setAttachmentType(
$this->canBeSupportedAt($blockReplace, $face) ?
BellAttachmentType::TWO_WALLS :
@@ -112,8 +115,8 @@ final class Bell extends Transparent{
foreach(match($this->attachmentType){
BellAttachmentType::CEILING => [Facing::UP],
BellAttachmentType::FLOOR => [Facing::DOWN],
- BellAttachmentType::ONE_WALL => [Facing::opposite($this->facing)],
- BellAttachmentType::TWO_WALLS => [$this->facing, Facing::opposite($this->facing)]
+ BellAttachmentType::ONE_WALL => [Facing::opposite($this->facing->toFacing())],
+ BellAttachmentType::TWO_WALLS => [$this->facing->toFacing(), Facing::opposite($this->facing->toFacing())]
} as $supportBlockDirection){
if(!$this->canBeSupportedAt($this, $supportBlockDirection)){
$this->position->getWorld()->useBreakOn($this->position);
@@ -122,7 +125,7 @@ final class Bell extends Transparent{
}
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){
$faceHit = Facing::opposite($player->getHorizontalFacing());
if($this->isValidFaceToRing($faceHit)){
@@ -141,7 +144,7 @@ final class Bell extends Transparent{
}
}
- public function ring(int $faceHit) : void{
+ public function ring(Facing $faceHit) : void{
$world = $this->position->getWorld();
$world->addSound($this->position, new BellRingSound());
$tile = $world->getTile($this->position);
@@ -154,11 +157,11 @@ final class Bell extends Transparent{
return [$this->asItem()];
}
- private function isValidFaceToRing(int $faceHit) : bool{
+ private function isValidFaceToRing(Facing $faceHit) : bool{
return match($this->attachmentType){
BellAttachmentType::CEILING => true,
- BellAttachmentType::FLOOR => Facing::axis($faceHit) === Facing::axis($this->facing),
- BellAttachmentType::ONE_WALL, BellAttachmentType::TWO_WALLS => $faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true),
+ BellAttachmentType::FLOOR => Facing::axis($faceHit) === Facing::axis($this->facing->toFacing()),
+ BellAttachmentType::ONE_WALL, BellAttachmentType::TWO_WALLS => $faceHit === Facing::rotateY($this->facing->toFacing(), false) || $faceHit === Facing::rotateY($this->facing->toFacing(), true),
};
}
}
diff --git a/src/block/BigDripleafHead.php b/src/block/BigDripleafHead.php
index a9b87bf7f..1244aff1c 100644
--- a/src/block/BigDripleafHead.php
+++ b/src/block/BigDripleafHead.php
@@ -80,8 +80,8 @@ class BigDripleafHead extends BaseBigDripleaf{
if(!$entity instanceof Projectile && $this->leafState === DripleafState::STABLE){
//the entity must be standing on top of the leaf - do not collapse if the entity is standing underneath
$intersection = AxisAlignedBB::one()
- ->offset($this->position->x, $this->position->y, $this->position->z)
- ->trim(Facing::DOWN, 1 - $this->getLeafTopOffset());
+ ->offsetCopy($this->position->x, $this->position->y, $this->position->z)
+ ->trimmedCopy(Facing::DOWN, 1 - $this->getLeafTopOffset());
if($entity->getBoundingBox()->intersectsWith($intersection)){
$this->setTiltAndScheduleTick(DripleafState::UNSTABLE);
return false;
@@ -116,8 +116,8 @@ class BigDripleafHead extends BaseBigDripleaf{
if($this->leafState !== DripleafState::FULL_TILT){
return [
AxisAlignedBB::one()
- ->trim(Facing::DOWN, 11 / 16)
- ->trim(Facing::UP, $this->getLeafTopOffset())
+ ->trimmedCopy(Facing::DOWN, 11 / 16)
+ ->trimmedCopy(Facing::UP, $this->getLeafTopOffset())
];
}
return [];
diff --git a/src/block/Block.php b/src/block/Block.php
index 36e08fc0b..7dd4723b0 100644
--- a/src/block/Block.php
+++ b/src/block/Block.php
@@ -424,7 +424,7 @@ class Block{
* Returns whether this block can replace the given block in the given placement conditions.
* This is used to allow slabs of the same type to combine into double slabs.
*/
- public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
+ public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, Facing $face, bool $isClickedBlock) : bool{
return $blockReplace->canBeReplaced();
}
@@ -436,13 +436,13 @@ class Block{
* @param Item $item Item used to place the block
* @param Block $blockReplace Block expected to be replaced
* @param Block $blockClicked Block that was clicked using the item
- * @param int $face Face of the clicked block which was clicked
+ * @param Facing $face Face of the clicked block which was clicked
* @param Vector3 $clickVector Exact position inside the clicked block where the click occurred, relative to the block's position
* @param Player|null $player Player who placed the block, or null if it was not a player
*
* @return bool whether the placement should go ahead
*/
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$tx->addBlock($blockReplace->position, $this);
return true;
}
@@ -524,7 +524,7 @@ class Block{
* @param Vector3 $clickVector Exact position where the click occurred, relative to the block's integer position
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
*/
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
return false;
}
@@ -533,7 +533,7 @@ class Block{
*
* @return bool if an action took place, prevents starting to break the block if true.
*/
- public function onAttack(Item $item, int $face, ?Player $player = null) : bool{
+ public function onAttack(Item $item, Facing $face, ?Player $player = null) : bool{
return false;
}
@@ -770,10 +770,10 @@ class Block{
*
* @return Block
*/
- public function getSide(int $side, int $step = 1){
+ public function getSide(Facing $side, int $step = 1){
$position = $this->position;
if($position->isValid()){
- [$dx, $dy, $dz] = Facing::OFFSET[$side] ?? [0, 0, 0];
+ [$dx, $dy, $dz] = Facing::OFFSET[$side->value] ?? [0, 0, 0];
return $position->getWorld()->getBlockAt(
$position->x + ($dx * $step),
$position->y + ($dy * $step),
@@ -793,7 +793,7 @@ class Block{
public function getHorizontalSides() : \Generator{
$world = $this->position->getWorld();
foreach(Facing::HORIZONTAL as $facing){
- [$dx, $dy, $dz] = Facing::OFFSET[$facing];
+ [$dx, $dy, $dz] = Facing::OFFSET[$facing->value];
//TODO: yield Facing as the key?
yield $world->getBlockAt(
$this->position->x + $dx,
@@ -914,11 +914,12 @@ class Block{
*/
final public function getCollisionBoxes() : array{
if($this->collisionBoxes === null){
- $this->collisionBoxes = $this->recalculateCollisionBoxes();
+ $collisionBoxes = $this->recalculateCollisionBoxes();
$extraOffset = $this->getModelPositionOffset();
$offset = $extraOffset !== null ? $this->position->addVector($extraOffset) : $this->position;
- foreach($this->collisionBoxes as $bb){
- $bb->offset($offset->x, $offset->y, $offset->z);
+ $this->collisionBoxes = [];
+ foreach($collisionBoxes as $bb){
+ $this->collisionBoxes[] = $bb->offsetCopy($offset->x, $offset->y, $offset->z);
}
}
@@ -945,11 +946,11 @@ class Block{
* Returns the type of support that the block can provide on the given face. This is used to determine whether
* blocks placed on the given face can be supported by this block.
*/
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::FULL;
}
- protected function getAdjacentSupportType(int $facing) : SupportType{
+ protected function getAdjacentSupportType(Facing $facing) : SupportType{
return $this->getSide($facing)->getSupportType(Facing::opposite($facing));
}
diff --git a/src/block/BlockBreakInfo.php b/src/block/BlockBreakInfo.php
index e77e06cfd..3d45caf3c 100644
--- a/src/block/BlockBreakInfo.php
+++ b/src/block/BlockBreakInfo.php
@@ -73,7 +73,7 @@ class BlockBreakInfo{
return new self(0.0, $toolType, $toolHarvestLevel, 0.0);
}
- public static function indestructible(float $blastResistance = 18000000.0) : self{
+ public static function indestructible(float $blastResistance = 18000003.75) : self{
return new self(-1.0, BlockToolType::NONE, 0, $blastResistance);
}
diff --git a/src/block/BlockTypeIds.php b/src/block/BlockTypeIds.php
index c440cefdc..e4d49746f 100644
--- a/src/block/BlockTypeIds.php
+++ b/src/block/BlockTypeIds.php
@@ -786,8 +786,44 @@ final class BlockTypeIds{
public const RESIN_BRICKS = 10756;
public const RESIN_CLUMP = 10757;
public const CHISELED_RESIN_BRICKS = 10758;
+ public const RESPAWN_ANCHOR = 10759;
+ public const OMINOUS_BANNER = 10760;
+ public const OMINOUS_WALL_BANNER = 10761;
+ public const ACACIA_CEILING_CENTER_HANGING_SIGN = 10762;
+ public const ACACIA_CEILING_EDGES_HANGING_SIGN = 10763;
+ public const ACACIA_WALL_HANGING_SIGN = 10764;
+ public const BIRCH_CEILING_CENTER_HANGING_SIGN = 10765;
+ public const BIRCH_CEILING_EDGES_HANGING_SIGN = 10766;
+ public const BIRCH_WALL_HANGING_SIGN = 10767;
+ public const CHERRY_CEILING_CENTER_HANGING_SIGN = 10768;
+ public const CHERRY_CEILING_EDGES_HANGING_SIGN = 10769;
+ public const CHERRY_WALL_HANGING_SIGN = 10770;
+ public const CRIMSON_CEILING_CENTER_HANGING_SIGN = 10771;
+ public const CRIMSON_CEILING_EDGES_HANGING_SIGN = 10772;
+ public const CRIMSON_WALL_HANGING_SIGN = 10773;
+ public const DARK_OAK_CEILING_CENTER_HANGING_SIGN = 10774;
+ public const DARK_OAK_CEILING_EDGES_HANGING_SIGN = 10775;
+ public const DARK_OAK_WALL_HANGING_SIGN = 10776;
+ public const JUNGLE_CEILING_CENTER_HANGING_SIGN = 10777;
+ public const JUNGLE_CEILING_EDGES_HANGING_SIGN = 10778;
+ public const JUNGLE_WALL_HANGING_SIGN = 10779;
+ public const MANGROVE_CEILING_CENTER_HANGING_SIGN = 10780;
+ public const MANGROVE_CEILING_EDGES_HANGING_SIGN = 10781;
+ public const MANGROVE_WALL_HANGING_SIGN = 10782;
+ public const OAK_CEILING_CENTER_HANGING_SIGN = 10783;
+ public const OAK_CEILING_EDGES_HANGING_SIGN = 10784;
+ public const OAK_WALL_HANGING_SIGN = 10785;
+ public const PALE_OAK_CEILING_CENTER_HANGING_SIGN = 10786;
+ public const PALE_OAK_CEILING_EDGES_HANGING_SIGN = 10787;
+ public const PALE_OAK_WALL_HANGING_SIGN = 10788;
+ public const SPRUCE_CEILING_CENTER_HANGING_SIGN = 10789;
+ public const SPRUCE_CEILING_EDGES_HANGING_SIGN = 10790;
+ public const SPRUCE_WALL_HANGING_SIGN = 10791;
+ public const WARPED_CEILING_CENTER_HANGING_SIGN = 10792;
+ public const WARPED_CEILING_EDGES_HANGING_SIGN = 10793;
+ public const WARPED_WALL_HANGING_SIGN = 10794;
- public const FIRST_UNUSED_BLOCK_ID = 10759;
+ public const FIRST_UNUSED_BLOCK_ID = 10795;
private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID;
diff --git a/src/block/BlockTypeTags.php b/src/block/BlockTypeTags.php
index 19a4825d9..531f3bcb3 100644
--- a/src/block/BlockTypeTags.php
+++ b/src/block/BlockTypeTags.php
@@ -31,4 +31,5 @@ final class BlockTypeTags{
public const SAND = self::PREFIX . "sand";
public const POTTABLE_PLANTS = self::PREFIX . "pottable";
public const FIRE = self::PREFIX . "fire";
+ public const HANGING_SIGN = self::PREFIX . "hanging_sign";
}
diff --git a/src/block/BoneBlock.php b/src/block/BoneBlock.php
index 247bdb748..465d96033 100644
--- a/src/block/BoneBlock.php
+++ b/src/block/BoneBlock.php
@@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\PillarRotation;
use pocketmine\block\utils\PillarRotationTrait;
-class BoneBlock extends Opaque{
+class BoneBlock extends Opaque implements PillarRotation{
use PillarRotationTrait;
}
diff --git a/src/block/BrewingStand.php b/src/block/BrewingStand.php
index 59e439b91..0184de199 100644
--- a/src/block/BrewingStand.php
+++ b/src/block/BrewingStand.php
@@ -52,17 +52,17 @@ class BrewingStand extends Transparent{
protected function recalculateCollisionBoxes() : array{
return [
//bottom slab part - in PC this is also inset on X/Z by 1/16, but Bedrock sucks
- AxisAlignedBB::one()->trim(Facing::UP, 7 / 8),
+ AxisAlignedBB::one()->trimmedCopy(Facing::UP, 7 / 8),
//center post
AxisAlignedBB::one()
- ->squash(Axis::X, 7 / 16)
- ->squash(Axis::Z, 7 / 16)
- ->trim(Facing::UP, 1 / 8)
+ ->squashedCopy(Axis::X, 7 / 16)
+ ->squashedCopy(Axis::Z, 7 / 16)
+ ->trimmedCopy(Facing::UP, 1 / 8)
];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -96,7 +96,7 @@ class BrewingStand extends Transparent{
return $this;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
$stand = $this->position->getWorld()->getTile($this->position);
if($stand instanceof TileBrewingStand && $stand->canOpenWith($item->getCustomName())){
diff --git a/src/block/Button.php b/src/block/Button.php
index 73bd1d556..04f7716f2 100644
--- a/src/block/Button.php
+++ b/src/block/Button.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\AnyFacing;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
@@ -33,13 +34,13 @@ use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\RedstonePowerOffSound;
use pocketmine\world\sound\RedstonePowerOnSound;
-abstract class Button extends Flowable{
+abstract class Button extends Flowable implements AnyFacing{
use AnyFacingTrait;
protected bool $pressed = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->facing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->pressed);
}
@@ -51,7 +52,7 @@ abstract class Button extends Flowable{
return $this;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedAt($blockReplace, $face)){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
@@ -61,7 +62,7 @@ abstract class Button extends Flowable{
abstract protected function getActivationTime() : int;
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if(!$this->pressed){
$this->pressed = true;
$world = $this->position->getWorld();
@@ -88,7 +89,7 @@ abstract class Button extends Flowable{
}
}
- private function canBeSupportedAt(Block $block, int $face) : bool{
+ private function canBeSupportedAt(Block $block, Facing $face) : bool{
return $block->getAdjacentSupportType(Facing::opposite($face))->hasCenterSupport();
}
}
diff --git a/src/block/Cactus.php b/src/block/Cactus.php
index 67b15b946..0e4d7c8ed 100644
--- a/src/block/Cactus.php
+++ b/src/block/Cactus.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\StaticSupportTrait;
@@ -33,7 +34,7 @@ use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
-class Cactus extends Transparent{
+class Cactus extends Transparent implements Ageable{
use AgeableTrait;
use StaticSupportTrait;
@@ -45,10 +46,10 @@ class Cactus extends Transparent{
protected function recalculateCollisionBoxes() : array{
$shrinkSize = 1 / 16;
- return [AxisAlignedBB::one()->contract($shrinkSize, 0, $shrinkSize)->trim(Facing::UP, $shrinkSize)];
+ return [AxisAlignedBB::one()->contractedCopy($shrinkSize, 0, $shrinkSize)->trimmedCopy(Facing::UP, $shrinkSize)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
diff --git a/src/block/Cake.php b/src/block/Cake.php
index e8c6dc93e..3f4f9db92 100644
--- a/src/block/Cake.php
+++ b/src/block/Cake.php
@@ -43,9 +43,9 @@ class Cake extends BaseCake{
protected function recalculateCollisionBoxes() : array{
return [
AxisAlignedBB::one()
- ->contract(1 / 16, 0, 1 / 16)
- ->trim(Facing::UP, 0.5)
- ->trim(Facing::WEST, $this->bites / 8)
+ ->contractedCopy(1 / 16, 0, 1 / 16)
+ ->trimmedCopy(Facing::UP, 0.5)
+ ->trimmedCopy(Facing::WEST, $this->bites / 8)
];
}
@@ -60,7 +60,7 @@ class Cake extends BaseCake{
return $this;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($this->bites === 0 && $item instanceof ItemBlock){
$block = $item->getBlock();
$resultBlock = null;
diff --git a/src/block/CakeWithCandle.php b/src/block/CakeWithCandle.php
index 546843d6c..09a1c1bfa 100644
--- a/src/block/CakeWithCandle.php
+++ b/src/block/CakeWithCandle.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CandleTrait;
+use pocketmine\block\utils\Lightable;
use pocketmine\entity\Living;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
@@ -31,7 +32,7 @@ use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
-class CakeWithCandle extends BaseCake{
+class CakeWithCandle extends BaseCake implements Lightable{
use CandleTrait {
onInteract as onInteractCandle;
}
@@ -39,8 +40,8 @@ class CakeWithCandle extends BaseCake{
protected function recalculateCollisionBoxes() : array{
return [
AxisAlignedBB::one()
- ->contract(1 / 16, 0, 1 / 16)
- ->trim(Facing::UP, 0.5) //TODO: not sure if the candle affects height
+ ->contractedCopy(1 / 16, 0, 1 / 16)
+ ->trimmedCopy(Facing::UP, 0.5) //TODO: not sure if the candle affects height
];
}
@@ -48,7 +49,7 @@ class CakeWithCandle extends BaseCake{
return VanillaBlocks::CANDLE();
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($this->lit && $face !== Facing::UP){
return true;
}
diff --git a/src/block/CakeWithDyedCandle.php b/src/block/CakeWithDyedCandle.php
index 0dff358e1..04ab0c6eb 100644
--- a/src/block/CakeWithDyedCandle.php
+++ b/src/block/CakeWithDyedCandle.php
@@ -23,10 +23,11 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\DyeColor;
-class CakeWithDyedCandle extends CakeWithCandle{
+class CakeWithDyedCandle extends CakeWithCandle implements Colored{
use ColoredTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
diff --git a/src/block/Campfire.php b/src/block/Campfire.php
index bb1a001c6..e8ea9913b 100644
--- a/src/block/Campfire.php
+++ b/src/block/Campfire.php
@@ -24,7 +24,10 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\tile\Campfire as TileCampfire;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
+use pocketmine\block\utils\Lightable;
use pocketmine\block\utils\LightableTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\crafting\FurnaceRecipe;
@@ -59,7 +62,7 @@ use function count;
use function min;
use function mt_rand;
-class Campfire extends Transparent{
+class Campfire extends Transparent implements Lightable, HorizontalFacing{
use HorizontalFacingTrait{
HorizontalFacingTrait::describeBlockOnlyState as encodeFacingState;
}
@@ -126,12 +129,12 @@ class Campfire extends Transparent{
];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 9 / 16)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 9 / 16)];
}
/**
@@ -170,18 +173,18 @@ class Campfire extends Transparent{
return $this->cookingTimes[$slot] ?? 0;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->getSide(Facing::DOWN) instanceof Campfire){
return false;
}
if($player !== null){
- $this->facing = $player->getHorizontalFacing();
+ $this->facing = HorizontalFacingOption::fromFacing($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{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if(!$this->lit){
if($item->getTypeId() === ItemTypeIds::FIRE_CHARGE){
$item->pop();
diff --git a/src/block/Candle.php b/src/block/Candle.php
index 7f22641e1..df129d961 100644
--- a/src/block/Candle.php
+++ b/src/block/Candle.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CandleTrait;
+use pocketmine\block\utils\Lightable;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
@@ -35,7 +36,7 @@ use pocketmine\player\Player;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\BlockTransaction;
-class Candle extends Transparent{
+class Candle extends Transparent implements Lightable{
use CandleTrait {
describeBlockOnlyState as encodeLitState;
getLightLevel as getBaseLightLevel;
@@ -70,27 +71,27 @@ class Candle extends Transparent{
return [
(match($this->count){
1 => AxisAlignedBB::one()
- ->squash(Axis::X, 7 / 16)
- ->squash(Axis::Z, 7 / 16),
+ ->squashedCopy(Axis::X, 7 / 16)
+ ->squashedCopy(Axis::Z, 7 / 16),
2 => AxisAlignedBB::one()
- ->squash(Axis::X, 5 / 16)
- ->trim(Facing::NORTH, 7 / 16) //0.3 thick on the Z axis
- ->trim(Facing::SOUTH, 6 / 16),
+ ->squashedCopy(Axis::X, 5 / 16)
+ ->trimmedCopy(Facing::NORTH, 7 / 16) //0.3 thick on the Z axis
+ ->trimmedCopy(Facing::SOUTH, 6 / 16),
3 => AxisAlignedBB::one()
- ->trim(Facing::WEST, 5 / 16)
- ->trim(Facing::EAST, 6 / 16)
- ->trim(Facing::NORTH, 6 / 16)
- ->trim(Facing::SOUTH, 5 / 16),
+ ->trimmedCopy(Facing::WEST, 5 / 16)
+ ->trimmedCopy(Facing::EAST, 6 / 16)
+ ->trimmedCopy(Facing::NORTH, 6 / 16)
+ ->trimmedCopy(Facing::SOUTH, 5 / 16),
4 => AxisAlignedBB::one()
- ->squash(Axis::X, 5 / 16)
- ->trim(Facing::NORTH, 5 / 16)
- ->trim(Facing::SOUTH, 6 / 16),
+ ->squashedCopy(Axis::X, 5 / 16)
+ ->trimmedCopy(Facing::NORTH, 5 / 16)
+ ->trimmedCopy(Facing::SOUTH, 6 / 16),
default => throw new AssumptionFailedError("Unreachable")
- })->trim(Facing::UP, 10 / 16)
+ })->trimmedCopy(Facing::UP, 10 / 16)
];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -98,12 +99,12 @@ class Candle extends Transparent{
return $block instanceof Candle && $block->hasSameTypeId($this) ? $block : null;
}
- public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
+ public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, Facing $face, bool $isClickedBlock) : bool{
$candle = $this->getCandleIfCompatibleType($blockReplace);
return $candle !== null ? $candle->count < self::MAX_COUNT : parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$blockReplace->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport()){
return false;
}
diff --git a/src/block/Carpet.php b/src/block/Carpet.php
index 2d8e7ea47..772a93eea 100644
--- a/src/block/Carpet.php
+++ b/src/block/Carpet.php
@@ -23,12 +23,13 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\StaticSupportTrait;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
-class Carpet extends Flowable{
+class Carpet extends Flowable implements Colored{
use ColoredTrait;
use StaticSupportTrait;
@@ -37,7 +38,7 @@ class Carpet extends Flowable{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 15 / 16)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 15 / 16)];
}
private function canBeSupportedAt(Block $block) : bool{
diff --git a/src/block/CartographyTable.php b/src/block/CartographyTable.php
index 1c3e94096..28ca59f7c 100644
--- a/src/block/CartographyTable.php
+++ b/src/block/CartographyTable.php
@@ -25,12 +25,13 @@ namespace pocketmine\block;
use pocketmine\block\inventory\window\CartographyTableInventoryWindow;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
final class CartographyTable extends Opaque{
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){
$player->setCurrentWindow(new CartographyTableInventoryWindow($player, $this->position));
}
diff --git a/src/block/CarvedPumpkin.php b/src/block/CarvedPumpkin.php
index 98f3c2307..cfdb8d49d 100644
--- a/src/block/CarvedPumpkin.php
+++ b/src/block/CarvedPumpkin.php
@@ -24,7 +24,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
-class CarvedPumpkin extends Opaque{
+class CarvedPumpkin extends Opaque implements HorizontalFacing{
use FacesOppositePlacingPlayerTrait;
}
diff --git a/src/block/Cauldron.php b/src/block/Cauldron.php
index 772583a5a..c44da1682 100644
--- a/src/block/Cauldron.php
+++ b/src/block/Cauldron.php
@@ -51,16 +51,16 @@ final class Cauldron extends Transparent{
protected function recalculateCollisionBoxes() : array{
$result = [
- AxisAlignedBB::one()->trim(Facing::UP, 11 / 16) //bottom of the cauldron
+ AxisAlignedBB::one()->trimmedCopy(Facing::UP, 11 / 16) //bottom of the cauldron
];
foreach(Facing::HORIZONTAL as $f){ //add the frame parts around the bowl
- $result[] = AxisAlignedBB::one()->trim($f, 14 / 16);
+ $result[] = AxisAlignedBB::one()->trimmedCopy($f, 14 / 16);
}
return $result;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return $facing === Facing::UP ? SupportType::EDGE : SupportType::NONE;
}
@@ -75,7 +75,7 @@ final class Cauldron extends Transparent{
$returnedItems[] = $returnedItem;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item->getTypeId() === ItemTypeIds::WATER_BUCKET){
$this->fill(FillableCauldron::MAX_FILL_LEVEL, VanillaBlocks::WATER_CAULDRON(), $item, VanillaItems::BUCKET(), $returnedItems);
}elseif($item->getTypeId() === ItemTypeIds::LAVA_BUCKET){
diff --git a/src/block/CaveVines.php b/src/block/CaveVines.php
index daa973507..1e42f2ac0 100644
--- a/src/block/CaveVines.php
+++ b/src/block/CaveVines.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\StaticSupportTrait;
@@ -39,7 +40,7 @@ use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\GlowBerriesPickSound;
use function mt_rand;
-class CaveVines extends Flowable{
+class CaveVines extends Flowable implements Ageable{
use AgeableTrait;
use StaticSupportTrait;
@@ -83,12 +84,12 @@ class CaveVines extends Flowable{
return $supportBlock->getSupportType(Facing::DOWN) === SupportType::FULL || $supportBlock->hasSameTypeId($this);
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->age = mt_rand(0, self::MAX_AGE);
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{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($this->berries){
$this->position->getWorld()->dropItem($this->position, $this->asItem());
$this->position->getWorld()->addSound($this->position, new GlowBerriesPickSound());
@@ -158,7 +159,7 @@ class CaveVines extends Flowable{
return VanillaItems::GLOW_BERRIES();
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
}
diff --git a/src/block/CeilingCenterHangingSign.php b/src/block/CeilingCenterHangingSign.php
new file mode 100644
index 000000000..4d9803617
--- /dev/null
+++ b/src/block/CeilingCenterHangingSign.php
@@ -0,0 +1,61 @@
+rotation = self::getRotationFromYaw($player->getLocation()->getYaw());
+ }
+ return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
+ }
+
+ private function canBeSupportedAt(Block $block) : bool{
+ $supportBlock = $block->getSide(Facing::UP);
+ return
+ $supportBlock->getSupportType(Facing::DOWN)->hasCenterSupport() ||
+ $supportBlock->hasTypeTag(BlockTypeTags::HANGING_SIGN);
+ }
+}
diff --git a/src/block/CeilingEdgesHangingSign.php b/src/block/CeilingEdgesHangingSign.php
new file mode 100644
index 000000000..8a7271863
--- /dev/null
+++ b/src/block/CeilingEdgesHangingSign.php
@@ -0,0 +1,69 @@
+facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
+ }
+ if(!$this->canBeSupportedAt($blockReplace)){
+ return false;
+ }
+
+ return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
+ }
+
+ public function onNearbyBlockChange() : void{
+ if(!$this->canBeSupportedAt($this)){
+ $this->position->getWorld()->useBreakOn($this->position);
+ }
+ }
+
+ private function canBeSupportedAt(Block $block) : bool{
+ $supportBlock = $block->getSide(Facing::UP);
+ return
+ $supportBlock->getSupportType(Facing::DOWN) === SupportType::FULL ||
+ (($supportBlock instanceof WallHangingSign || $supportBlock instanceof CeilingEdgesHangingSign) && Facing::axis($supportBlock->getFacing()->toFacing()) === Facing::axis($this->facing->toFacing()));
+ }
+}
diff --git a/src/block/Chain.php b/src/block/Chain.php
index e9cc2c9be..12b379852 100644
--- a/src/block/Chain.php
+++ b/src/block/Chain.php
@@ -23,16 +23,17 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\PillarRotation;
use pocketmine\block\utils\PillarRotationTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
-final class Chain extends Transparent{
+final class Chain extends Transparent implements PillarRotation{
use PillarRotationTrait;
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return $this->axis === Axis::Y && Facing::axis($facing) === Axis::Y ? SupportType::CENTER : SupportType::NONE;
}
@@ -40,7 +41,7 @@ final class Chain extends Transparent{
$bb = AxisAlignedBB::one();
foreach([Axis::Y, Axis::Z, Axis::X] as $axis){
if($axis !== $this->axis){
- $bb->squash($axis, 13 / 32);
+ $bb = $bb->squashedCopy($axis, 13 / 32);
}
}
return [$bb];
diff --git a/src/block/ChemistryTable.php b/src/block/ChemistryTable.php
index 058e40288..c266bd513 100644
--- a/src/block/ChemistryTable.php
+++ b/src/block/ChemistryTable.php
@@ -24,14 +24,16 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
-final class ChemistryTable extends Opaque{
+final class ChemistryTable extends Opaque implements HorizontalFacing{
use FacesOppositePlacingPlayerTrait;
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
//TODO
return false;
}
diff --git a/src/block/Chest.php b/src/block/Chest.php
index 414648d37..c5ae39f26 100644
--- a/src/block/Chest.php
+++ b/src/block/Chest.php
@@ -29,6 +29,7 @@ use pocketmine\block\tile\Chest as TileChest;
use pocketmine\block\utils\AnimatedContainer;
use pocketmine\block\utils\AnimatedContainerTrait;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\ChestPairEvent;
use pocketmine\item\Item;
@@ -43,16 +44,16 @@ use pocketmine\world\sound\ChestCloseSound;
use pocketmine\world\sound\ChestOpenSound;
use pocketmine\world\sound\Sound;
-class Chest extends Transparent implements AnimatedContainer{
+class Chest extends Transparent implements AnimatedContainer, HorizontalFacing{
use AnimatedContainerTrait;
use FacesOppositePlacingPlayerTrait;
protected function recalculateCollisionBoxes() : array{
//these are slightly bigger than in PC
- return [AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05)];
+ return [AxisAlignedBB::one()->contractedCopy(0.025, 0, 0.025)->trimmedCopy(Facing::UP, 0.05)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -64,7 +65,7 @@ class Chest extends Transparent implements AnimatedContainer{
$tile = $world->getTile($position);
if($tile instanceof TileChest){
foreach([false, true] as $clockwise){
- $side = Facing::rotateY($this->facing, $clockwise);
+ $side = Facing::rotateY($this->facing->toFacing(), $clockwise);
$c = $position->getSide($side);
$pair = $world->getTile($c);
if($pair instanceof TileChest && $pair->isPaired() && $pair->getPair() === $tile){
@@ -80,7 +81,7 @@ class Chest extends Transparent implements AnimatedContainer{
$tile = $world->getTile($this->position);
if($tile instanceof TileChest){
foreach([false, true] as $clockwise){
- $side = Facing::rotateY($this->facing, $clockwise);
+ $side = Facing::rotateY($this->facing->toFacing(), $clockwise);
$c = $this->getSide($side);
if($c instanceof Chest && $c->hasSameTypeId($this) && $c->facing === $this->facing){
$pair = $world->getTile($c->position);
@@ -99,7 +100,7 @@ class Chest extends Transparent implements AnimatedContainer{
}
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
$world = $this->position->getWorld();
$chest = $world->getTile($this->position);
diff --git a/src/block/ChiseledBookshelf.php b/src/block/ChiseledBookshelf.php
index 73c4861bf..d35848331 100644
--- a/src/block/ChiseledBookshelf.php
+++ b/src/block/ChiseledBookshelf.php
@@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\ChiseledBookshelf as TileChiseledBookshelf;
use pocketmine\block\utils\ChiseledBookshelfSlot;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Book;
@@ -38,7 +39,7 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use function spl_object_id;
-class ChiseledBookshelf extends Opaque{
+class ChiseledBookshelf extends Opaque implements HorizontalFacing{
use HorizontalFacingTrait;
use FacesOppositePlacingPlayerTrait;
@@ -51,7 +52,7 @@ class ChiseledBookshelf extends Opaque{
private ?ChiseledBookshelfSlot $lastInteractedSlot = null;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->enumSet($this->slots, ChiseledBookshelfSlot::cases());
}
@@ -113,6 +114,18 @@ class ChiseledBookshelf extends Opaque{
return $this->slots;
}
+ /**
+ * @param ChiseledBookshelfSlot[] $slots
+ * @return $this
+ */
+ public function setSlots(array $slots) : self{
+ $this->slots = [];
+ foreach($slots as $slot){
+ $this->setSlot($slot, true);
+ }
+ return $this;
+ }
+
/**
* Returns the last slot interacted by a player or null if no slot has been interacted with yet.
*/
@@ -130,8 +143,8 @@ class ChiseledBookshelf extends Opaque{
return $this;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
- if($face !== $this->facing){
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ if($face !== $this->facing->toFacing()){
return false;
}
diff --git a/src/block/ChorusFlower.php b/src/block/ChorusFlower.php
index cc3c606d9..14cce40ac 100644
--- a/src/block/ChorusFlower.php
+++ b/src/block/ChorusFlower.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\StaticSupportTrait;
use pocketmine\entity\projectile\Projectile;
@@ -40,7 +41,7 @@ use function array_rand;
use function min;
use function mt_rand;
-final class ChorusFlower extends Flowable{
+final class ChorusFlower extends Flowable implements Ageable{
use AgeableTrait;
use StaticSupportTrait;
@@ -105,9 +106,9 @@ final class ChorusFlower extends Flowable{
return [$stemHeight, $endStoneBelow];
}
- private function allHorizontalBlocksEmpty(World $world, Vector3 $position, ?int $except) : bool{
+ private function allHorizontalBlocksEmpty(World $world, Vector3 $position, ?Facing $except) : bool{
foreach($position->sidesAroundAxis(Axis::Y) as $facing => $sidePosition){
- if($facing === $except){
+ if($facing === $except?->value){
continue;
}
if($world->getBlock($sidePosition)->getTypeId() !== BlockTypeIds::AIR){
@@ -148,7 +149,7 @@ final class ChorusFlower extends Flowable{
return $this->allHorizontalBlocksEmpty($world, $up, null);
}
- private function grow(int $facing, int $ageChange, ?BlockTransaction $tx) : BlockTransaction{
+ private function grow(Facing $facing, int $ageChange, ?BlockTransaction $tx) : BlockTransaction{
if($tx === null){
$tx = new BlockTransaction($this->position->getWorld());
}
@@ -175,10 +176,10 @@ final class ChorusFlower extends Flowable{
$facingVisited = [];
for($attempts = 0, $maxAttempts = mt_rand(0, $endStoneBelow ? 4 : 3); $attempts < $maxAttempts; $attempts++){
$facing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)];
- if(isset($facingVisited[$facing])){
+ if(isset($facingVisited[$facing->value])){
continue;
}
- $facingVisited[$facing] = true;
+ $facingVisited[$facing->value] = true;
$sidePosition = $this->position->getSide($facing);
if(
diff --git a/src/block/ChorusPlant.php b/src/block/ChorusPlant.php
index 88cf1787c..96a203a10 100644
--- a/src/block/ChorusPlant.php
+++ b/src/block/ChorusPlant.php
@@ -43,8 +43,8 @@ final class ChorusPlant extends Flowable{
protected function recalculateCollisionBoxes() : array{
$bb = AxisAlignedBB::one();
foreach(Facing::ALL as $facing){
- if(!isset($this->connections[$facing])){
- $bb->trim($facing, 2 / 16);
+ if(!isset($this->connections[$facing->value])){
+ $bb = $bb->trimmedCopy($facing, 2 / 16);
}
}
@@ -62,9 +62,9 @@ final class ChorusPlant extends Flowable{
BlockTypeIds::END_STONE, BlockTypeIds::CHORUS_FLOWER, $this->getTypeId() => true,
default => false
}){
- $this->connections[$facing] = true;
+ $this->connections[$facing->value] = true;
}else{
- unset($this->connections[$facing]);
+ unset($this->connections[$facing->value]);
}
}
diff --git a/src/block/CocoaBlock.php b/src/block/CocoaBlock.php
index 83e1de34b..8cc60872c 100644
--- a/src/block/CocoaBlock.php
+++ b/src/block/CocoaBlock.php
@@ -23,15 +23,17 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\WoodType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
-use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
@@ -39,25 +41,26 @@ use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use function mt_rand;
-class CocoaBlock extends Flowable{
+class CocoaBlock extends Flowable implements Ageable, HorizontalFacing{
use HorizontalFacingTrait;
use AgeableTrait;
public const MAX_AGE = 2;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->boundedIntAuto(0, self::MAX_AGE, $this->age);
}
protected function recalculateCollisionBoxes() : array{
+ $realFacing = $this->facing->toFacing();
return [
AxisAlignedBB::one()
- ->squash(Facing::axis(Facing::rotateY($this->facing, true)), (6 - $this->age) / 16) //sides
- ->trim(Facing::DOWN, (7 - $this->age * 2) / 16)
- ->trim(Facing::UP, 0.25)
- ->trim(Facing::opposite($this->facing), 1 / 16) //gap between log and pod
- ->trim($this->facing, (11 - $this->age * 2) / 16) //outward face
+ ->squashedCopy(Facing::axis(Facing::rotateY($realFacing, true)), (6 - $this->age) / 16) //sides
+ ->trimmedCopy(Facing::DOWN, (7 - $this->age * 2) / 16)
+ ->trimmedCopy(Facing::UP, 0.25)
+ ->trimmedCopy(Facing::opposite($realFacing), 1 / 16) //gap between log and pod
+ ->trimmedCopy($realFacing, (11 - $this->age * 2) / 16) //outward face
];
}
@@ -65,16 +68,16 @@ class CocoaBlock extends Flowable{
return $block instanceof Wood && $block->getWoodType() === WoodType::JUNGLE;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
- if(Facing::axis($face) !== Axis::Y && $this->canAttachTo($blockClicked)){
- $this->facing = $face;
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ if(($hzFacing = HorizontalFacingOption::tryFromFacing($face)) !== null && $this->canAttachTo($blockClicked)){
+ $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
return false;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
@@ -85,7 +88,7 @@ class CocoaBlock extends Flowable{
}
public function onNearbyBlockChange() : void{
- if(!$this->canAttachTo($this->getSide(Facing::opposite($this->facing)))){
+ if(!$this->canAttachTo($this->getSide(Facing::opposite($this->facing->toFacing())))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
diff --git a/src/block/Concrete.php b/src/block/Concrete.php
index fae6f8e2f..6cad11193 100644
--- a/src/block/Concrete.php
+++ b/src/block/Concrete.php
@@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
-class Concrete extends Opaque{
+class Concrete extends Opaque implements Colored{
use ColoredTrait;
}
diff --git a/src/block/ConcretePowder.php b/src/block/ConcretePowder.php
index 59f14bc72..89b53053b 100644
--- a/src/block/ConcretePowder.php
+++ b/src/block/ConcretePowder.php
@@ -24,12 +24,13 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\Fallable;
use pocketmine\block\utils\FallableTrait;
use pocketmine\math\Facing;
-class ConcretePowder extends Opaque implements Fallable{
+class ConcretePowder extends Opaque implements Fallable, Colored{
use ColoredTrait;
use FallableTrait {
onNearbyBlockChange as protected startFalling;
diff --git a/src/block/CopperBulb.php b/src/block/CopperBulb.php
index 97fc209fe..d0bdedf3c 100644
--- a/src/block/CopperBulb.php
+++ b/src/block/CopperBulb.php
@@ -26,11 +26,13 @@ namespace pocketmine\block;
use pocketmine\block\utils\CopperMaterial;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\CopperTrait;
+use pocketmine\block\utils\Lightable;
use pocketmine\block\utils\LightableTrait;
+use pocketmine\block\utils\PoweredByRedstone;
use pocketmine\block\utils\PoweredByRedstoneTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
-class CopperBulb extends Opaque implements CopperMaterial{
+class CopperBulb extends Opaque implements CopperMaterial, Lightable, PoweredByRedstone{
use CopperTrait;
use PoweredByRedstoneTrait;
use LightableTrait{
diff --git a/src/block/CopperDoor.php b/src/block/CopperDoor.php
index 82a611206..6a690a109 100644
--- a/src/block/CopperDoor.php
+++ b/src/block/CopperDoor.php
@@ -35,7 +35,7 @@ class CopperDoor extends Door implements CopperMaterial{
onInteract as onInteractCopper;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $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);
diff --git a/src/block/CopperTrapdoor.php b/src/block/CopperTrapdoor.php
index e7d56fa0c..16a7d4ec0 100644
--- a/src/block/CopperTrapdoor.php
+++ b/src/block/CopperTrapdoor.php
@@ -26,6 +26,7 @@ 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;
@@ -34,7 +35,7 @@ class CopperTrapdoor extends Trapdoor implements CopperMaterial{
onInteract as onInteractCopper;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if ($player !== null && $player->isSneaking() && $this->onInteractCopper($item, $face, $clickVector, $player, $returnedItems)) {
return true;
}
diff --git a/src/block/CoralBlock.php b/src/block/CoralBlock.php
index 3e7ca8224..c21209998 100644
--- a/src/block/CoralBlock.php
+++ b/src/block/CoralBlock.php
@@ -24,11 +24,12 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
+use pocketmine\block\utils\CoralMaterial;
use pocketmine\block\utils\CoralTypeTrait;
use pocketmine\item\Item;
use function mt_rand;
-final class CoralBlock extends Opaque{
+final class CoralBlock extends Opaque implements CoralMaterial{
use CoralTypeTrait;
public function onNearbyBlockChange() : void{
diff --git a/src/block/CraftingTable.php b/src/block/CraftingTable.php
index 2b73d221a..99d509660 100644
--- a/src/block/CraftingTable.php
+++ b/src/block/CraftingTable.php
@@ -25,12 +25,13 @@ namespace pocketmine\block;
use pocketmine\block\inventory\window\CraftingTableInventoryWindow;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
class CraftingTable extends Opaque{
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
$player->setCurrentWindow(new CraftingTableInventoryWindow($player, $this->position));
}
diff --git a/src/block/Crops.php b/src/block/Crops.php
index e90ac6236..85cddcbed 100644
--- a/src/block/Crops.php
+++ b/src/block/Crops.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\CropGrowthHelper;
@@ -34,7 +35,7 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use function mt_rand;
-abstract class Crops extends Flowable{
+abstract class Crops extends Flowable implements Ageable{
use AgeableTrait;
use StaticSupportTrait;
@@ -44,7 +45,7 @@ abstract class Crops extends Flowable{
return $block->getSide(Facing::DOWN)->getTypeId() === BlockTypeIds::FARMLAND;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($this->age < self::MAX_AGE && $item instanceof Fertilizer){
$block = clone $this;
$tempAge = $block->age + mt_rand(2, 5);
diff --git a/src/block/DaylightSensor.php b/src/block/DaylightSensor.php
index 5720af529..ac3833753 100644
--- a/src/block/DaylightSensor.php
+++ b/src/block/DaylightSensor.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\AnalogRedstoneSignalEmitter;
use pocketmine\block\utils\AnalogRedstoneSignalEmitterTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -36,7 +37,7 @@ use function max;
use function round;
use const M_PI;
-class DaylightSensor extends Transparent{
+class DaylightSensor extends Transparent implements AnalogRedstoneSignalEmitter{
use AnalogRedstoneSignalEmitterTrait;
protected bool $inverted = false;
@@ -63,14 +64,14 @@ class DaylightSensor extends Transparent{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 10 / 16)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 10 / 16)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$this->inverted = !$this->inverted;
$this->signalStrength = $this->recalculateSignalStrength();
$this->position->getWorld()->setBlock($this->position, $this);
diff --git a/src/block/Dirt.php b/src/block/Dirt.php
index 104080d31..f106edc48 100644
--- a/src/block/Dirt.php
+++ b/src/block/Dirt.php
@@ -52,7 +52,7 @@ class Dirt extends Opaque{
return $this;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$world = $this->position->getWorld();
if($face !== Facing::DOWN && $item instanceof Hoe){
$up = $this->getSide(Facing::UP);
diff --git a/src/block/Door.php b/src/block/Door.php
index fa88267e1..559c71575 100644
--- a/src/block/Door.php
+++ b/src/block/Door.php
@@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -34,7 +36,7 @@ use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\DoorSound;
-class Door extends Transparent{
+class Door extends Transparent implements HorizontalFacing{
use HorizontalFacingTrait;
protected bool $top = false;
@@ -42,7 +44,7 @@ class Door extends Transparent{
protected bool $open = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->top);
$w->bool($this->hingeRight);
$w->bool($this->open);
@@ -97,10 +99,10 @@ class Door extends Transparent{
protected function recalculateCollisionBoxes() : array{
//TODO: doors are 0.1825 blocks thick, instead of 0.1875 like JE (https://bugs.mojang.com/browse/MCPE-19214)
- return [AxisAlignedBB::one()->trim($this->open ? Facing::rotateY($this->facing, !$this->hingeRight) : $this->facing, 327 / 400)];
+ return [AxisAlignedBB::one()->trimmedCopy($this->open ? Facing::rotateY($this->facing->toFacing(), !$this->hingeRight) : $this->facing->toFacing(), 327 / 400)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -110,7 +112,7 @@ class Door extends Transparent{
}
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::UP){
$blockUp = $this->getSide(Facing::UP);
if(!$blockUp->canBeReplaced() || !$this->canBeSupportedAt($blockReplace)){
@@ -118,11 +120,13 @@ class Door extends Transparent{
}
if($player !== null){
- $this->facing = $player->getHorizontalFacing();
+ //TODO: not sure if entities should use HorizontalFacingOption too
+ $this->facing = HorizontalFacingOption::fromFacing($player->getHorizontalFacing());
}
- $next = $this->getSide(Facing::rotateY($this->facing, false));
- $next2 = $this->getSide(Facing::rotateY($this->facing, true));
+ $realFacing = $this->facing->toFacing();
+ $next = $this->getSide(Facing::rotateY($realFacing, false));
+ $next2 = $this->getSide(Facing::rotateY($realFacing, true));
if($next->hasSameTypeId($this) || (!$next2->isTransparent() && $next->isTransparent())){ //Door hinge
$this->hingeRight = true;
@@ -138,7 +142,7 @@ class Door extends Transparent{
return false;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$this->open = !$this->open;
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
diff --git a/src/block/DoublePitcherCrop.php b/src/block/DoublePitcherCrop.php
index 1233ed05d..a4031d2d2 100644
--- a/src/block/DoublePitcherCrop.php
+++ b/src/block/DoublePitcherCrop.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\CropGrowthHelper;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -37,7 +38,7 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-final class DoublePitcherCrop extends DoublePlant{
+final class DoublePitcherCrop extends DoublePlant implements Ageable{
use AgeableTrait {
describeBlockOnlyState as describeAge;
}
@@ -57,10 +58,10 @@ final class DoublePitcherCrop extends DoublePlant{
//the pod exists only in the bottom half of the plant
return [
AxisAlignedBB::one()
- ->trim(Facing::UP, 11 / 16)
- ->squash(Axis::X, 3 / 16)
- ->squash(Axis::Z, 3 / 16)
- ->extend(Facing::DOWN, 1 / 16) //presumably this is to correct for farmland being 15/16 of a block tall
+ ->trimmedCopy(Facing::UP, 11 / 16)
+ ->squashedCopy(Axis::X, 3 / 16)
+ ->squashedCopy(Axis::Z, 3 / 16)
+ ->extendedCopy(Facing::DOWN, 1 / 16) //presumably this is to correct for farmland being 15/16 of a block tall
];
}
@@ -88,7 +89,7 @@ final class DoublePitcherCrop extends DoublePlant{
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
return true;
diff --git a/src/block/DoublePlant.php b/src/block/DoublePlant.php
index aab6d5b04..d1f878561 100644
--- a/src/block/DoublePlant.php
+++ b/src/block/DoublePlant.php
@@ -45,7 +45,7 @@ class DoublePlant extends Flowable{
return $this;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $blockReplace->getSide(Facing::DOWN);
if($down->hasTypeTag(BlockTypeTags::DIRT) && $blockReplace->getSide(Facing::UP)->canBeReplaced()){
$top = clone $this;
diff --git a/src/block/DragonEgg.php b/src/block/DragonEgg.php
index 10fec6394..89ec4237f 100644
--- a/src/block/DragonEgg.php
+++ b/src/block/DragonEgg.php
@@ -28,6 +28,7 @@ use pocketmine\block\utils\FallableTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\BlockTeleportEvent;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\GameMode;
use pocketmine\player\Player;
@@ -44,12 +45,12 @@ class DragonEgg extends Transparent implements Fallable{
return 1;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$this->teleport();
return true;
}
- public function onAttack(Item $item, int $face, ?Player $player = null) : bool{
+ public function onAttack(Item $item, Facing $face, ?Player $player = null) : bool{
if($player !== null && $player->getGamemode() !== GameMode::CREATIVE){
$this->teleport();
return true;
@@ -81,7 +82,7 @@ class DragonEgg extends Transparent implements Fallable{
}
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
}
diff --git a/src/block/DyedCandle.php b/src/block/DyedCandle.php
index a495e8d00..57a8b5923 100644
--- a/src/block/DyedCandle.php
+++ b/src/block/DyedCandle.php
@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
-class DyedCandle extends Candle{
+class DyedCandle extends Candle implements Colored{
use ColoredTrait;
protected function getCandleIfCompatibleType(Block $block) : ?Candle{
diff --git a/src/block/DyedShulkerBox.php b/src/block/DyedShulkerBox.php
index 5eae9237e..8be2718a2 100644
--- a/src/block/DyedShulkerBox.php
+++ b/src/block/DyedShulkerBox.php
@@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
-final class DyedShulkerBox extends ShulkerBox{
+final class DyedShulkerBox extends ShulkerBox implements Colored{
use ColoredTrait;
}
diff --git a/src/block/EnchantingTable.php b/src/block/EnchantingTable.php
index a5ac989d4..2344ae793 100644
--- a/src/block/EnchantingTable.php
+++ b/src/block/EnchantingTable.php
@@ -34,14 +34,14 @@ use pocketmine\player\Player;
class EnchantingTable extends Transparent{
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 0.25)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 0.25)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
//TODO lock
diff --git a/src/block/EndPortalFrame.php b/src/block/EndPortalFrame.php
index ed5b77433..52111090c 100644
--- a/src/block/EndPortalFrame.php
+++ b/src/block/EndPortalFrame.php
@@ -24,17 +24,18 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
-class EndPortalFrame extends Opaque{
+class EndPortalFrame extends Opaque implements HorizontalFacing{
use FacesOppositePlacingPlayerTrait;
protected bool $eye = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->eye);
}
@@ -51,6 +52,6 @@ class EndPortalFrame extends Opaque{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 3 / 16)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 3 / 16)];
}
}
diff --git a/src/block/EndRod.php b/src/block/EndRod.php
index a6770f370..b1cd64749 100644
--- a/src/block/EndRod.php
+++ b/src/block/EndRod.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\AnyFacing;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\item\Item;
use pocketmine\math\Axis;
@@ -32,10 +33,10 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-class EndRod extends Flowable{
+class EndRod extends Flowable implements AnyFacing{
use AnyFacingTrait;
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->facing = $face;
if($blockClicked instanceof EndRod && $blockClicked->facing === $this->facing){
$this->facing = Facing::opposite($face);
@@ -60,7 +61,7 @@ class EndRod extends Flowable{
if($axis === $myAxis){
continue;
}
- $bb->squash($axis, 6 / 16);
+ $bb->squashedCopy($axis, 6 / 16);
}
return [$bb];
}
diff --git a/src/block/EnderChest.php b/src/block/EnderChest.php
index 0d1d7fd5c..70eb739ff 100644
--- a/src/block/EnderChest.php
+++ b/src/block/EnderChest.php
@@ -28,6 +28,7 @@ use pocketmine\block\tile\EnderChest as TileEnderChest;
use pocketmine\block\utils\AnimatedContainer;
use pocketmine\block\utils\AnimatedContainerTrait;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
@@ -41,7 +42,7 @@ use pocketmine\world\sound\EnderChestCloseSound;
use pocketmine\world\sound\EnderChestOpenSound;
use pocketmine\world\sound\Sound;
-class EnderChest extends Transparent implements AnimatedContainer{
+class EnderChest extends Transparent implements AnimatedContainer, HorizontalFacing{
use AnimatedContainerTrait {
onContainerOpen as private traitOnContainerOpen;
onContainerClose as private traitOnContainerClose;
@@ -54,14 +55,14 @@ class EnderChest extends Transparent implements AnimatedContainer{
protected function recalculateCollisionBoxes() : array{
//these are slightly bigger than in PC
- return [AxisAlignedBB::one()->contract(0.025, 0, 0.025)->trim(Facing::UP, 0.05)];
+ return [AxisAlignedBB::one()->contractedCopy(0.025, 0, 0.025)->trimmedCopy(Facing::UP, 0.05)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
$enderChest = $this->position->getWorld()->getTile($this->position);
if($enderChest instanceof TileEnderChest && $this->getSide(Facing::UP)->isTransparent()){
diff --git a/src/block/Farmland.php b/src/block/Farmland.php
index 83bc34561..d0f92a528 100644
--- a/src/block/Farmland.php
+++ b/src/block/Farmland.php
@@ -95,7 +95,7 @@ class Farmland extends Transparent{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 16)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 1 / 16)];
}
public function onNearbyBlockChange() : void{
diff --git a/src/block/Fence.php b/src/block/Fence.php
index 52256d9f0..1eb8ef900 100644
--- a/src/block/Fence.php
+++ b/src/block/Fence.php
@@ -45,9 +45,9 @@ class Fence extends Transparent{
foreach(Facing::HORIZONTAL as $facing){
$block = $this->getSide($facing);
if($block instanceof static || $block instanceof FenceGate || $block->getSupportType(Facing::opposite($facing)) === SupportType::FULL){
- $this->connections[$facing] = true;
+ $this->connections[$facing->value] = true;
}else{
- unset($this->connections[$facing]);
+ unset($this->connections[$facing->value]);
}
}
@@ -59,43 +59,43 @@ class Fence extends Transparent{
$bbs = [];
- $connectWest = isset($this->connections[Facing::WEST]);
- $connectEast = isset($this->connections[Facing::EAST]);
+ $connectWest = isset($this->connections[Facing::WEST->value]);
+ $connectEast = isset($this->connections[Facing::EAST->value]);
if($connectWest || $connectEast){
//X axis (west/east)
$bbs[] = AxisAlignedBB::one()
- ->squash(Axis::Z, $inset)
- ->extend(Facing::UP, 0.5)
- ->trim(Facing::WEST, $connectWest ? 0 : $inset)
- ->trim(Facing::EAST, $connectEast ? 0 : $inset);
+ ->squashedCopy(Axis::Z, $inset)
+ ->extendedCopy(Facing::UP, 0.5)
+ ->trimmedCopy(Facing::WEST, $connectWest ? 0 : $inset)
+ ->trimmedCopy(Facing::EAST, $connectEast ? 0 : $inset);
}
- $connectNorth = isset($this->connections[Facing::NORTH]);
- $connectSouth = isset($this->connections[Facing::SOUTH]);
+ $connectNorth = isset($this->connections[Facing::NORTH->value]);
+ $connectSouth = isset($this->connections[Facing::SOUTH->value]);
if($connectNorth || $connectSouth){
//Z axis (north/south)
$bbs[] = AxisAlignedBB::one()
- ->squash(Axis::X, $inset)
- ->extend(Facing::UP, 0.5)
- ->trim(Facing::NORTH, $connectNorth ? 0 : $inset)
- ->trim(Facing::SOUTH, $connectSouth ? 0 : $inset);
+ ->squashedCopy(Axis::X, $inset)
+ ->extendedCopy(Facing::UP, 0.5)
+ ->trimmedCopy(Facing::NORTH, $connectNorth ? 0 : $inset)
+ ->trimmedCopy(Facing::SOUTH, $connectSouth ? 0 : $inset);
}
if(count($bbs) === 0){
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
return [
AxisAlignedBB::one()
- ->extend(Facing::UP, 0.5)
- ->contract($inset, 0, $inset)
+ ->extendedCopy(Facing::UP, 0.5)
+ ->contractedCopy($inset, 0, $inset)
];
}
return $bbs;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return Facing::axis($facing) === Axis::Y ? SupportType::CENTER : SupportType::NONE;
}
}
diff --git a/src/block/FenceGate.php b/src/block/FenceGate.php
index 2bbfdf892..a067bb71a 100644
--- a/src/block/FenceGate.php
+++ b/src/block/FenceGate.php
@@ -23,8 +23,11 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodTypeTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
@@ -35,7 +38,7 @@ use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\DoorSound;
-class FenceGate extends Transparent{
+class FenceGate extends Transparent implements HorizontalFacing, WoodMaterial{
use WoodTypeTrait;
use HorizontalFacingTrait;
@@ -43,7 +46,7 @@ class FenceGate extends Transparent{
protected bool $inWall = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->open);
$w->bool($this->inWall);
}
@@ -65,23 +68,24 @@ class FenceGate extends Transparent{
}
protected function recalculateCollisionBoxes() : array{
- return $this->open ? [] : [AxisAlignedBB::one()->extend(Facing::UP, 0.5)->squash(Facing::axis($this->facing), 6 / 16)];
+ return $this->open ? [] : [AxisAlignedBB::one()->extendedCopy(Facing::UP, 0.5)->squashedCopy(Facing::axis($this->facing->toFacing()), 6 / 16)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
private function checkInWall() : bool{
+ $realFacing = $this->facing->toFacing();
return (
- $this->getSide(Facing::rotateY($this->facing, false)) instanceof Wall ||
- $this->getSide(Facing::rotateY($this->facing, true)) instanceof Wall
+ $this->getSide(Facing::rotateY($realFacing, false)) instanceof Wall ||
+ $this->getSide(Facing::rotateY($realFacing, true)) instanceof Wall
);
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
- $this->facing = $player->getHorizontalFacing();
+ $this->facing = HorizontalFacingOption::fromFacing($player->getHorizontalFacing());
}
$this->inWall = $this->checkInWall();
@@ -97,12 +101,12 @@ class FenceGate extends Transparent{
}
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$this->open = !$this->open;
if($this->open && $player !== null){
$playerFacing = $player->getHorizontalFacing();
- if($playerFacing === Facing::opposite($this->facing)){
- $this->facing = $playerFacing;
+ if($playerFacing === Facing::opposite($this->facing->toFacing())){
+ $this->facing = HorizontalFacingOption::fromFacing($playerFacing);
}
}
diff --git a/src/block/FillableCauldron.php b/src/block/FillableCauldron.php
index ceef35299..f6ff3e458 100644
--- a/src/block/FillableCauldron.php
+++ b/src/block/FillableCauldron.php
@@ -54,16 +54,16 @@ abstract class FillableCauldron extends Transparent{
protected function recalculateCollisionBoxes() : array{
$result = [
- AxisAlignedBB::one()->trim(Facing::UP, 11 / 16) //bottom of the cauldron
+ AxisAlignedBB::one()->trimmedCopy(Facing::UP, 11 / 16) //bottom of the cauldron
];
foreach(Facing::HORIZONTAL as $f){ //add the frame parts around the bowl
- $result[] = AxisAlignedBB::one()->trim($f, 14 / 16);
+ $result[] = AxisAlignedBB::one()->trimmedCopy($f, 14 / 16);
}
return $result;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return $facing === Facing::UP ? SupportType::EDGE : SupportType::NONE;
}
diff --git a/src/block/Fire.php b/src/block/Fire.php
index 35a7a696c..62809fb9d 100644
--- a/src/block/Fire.php
+++ b/src/block/Fire.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\SupportType;
@@ -35,7 +36,7 @@ use function max;
use function min;
use function mt_rand;
-class Fire extends BaseFire{
+class Fire extends BaseFire implements Ageable{
use AgeableTrait;
public const MAX_AGE = 15;
diff --git a/src/block/FloorBanner.php b/src/block/FloorBanner.php
index 73bc45787..5df7bfb61 100644
--- a/src/block/FloorBanner.php
+++ b/src/block/FloorBanner.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\SignLikeRotation;
use pocketmine\block\utils\SignLikeRotationTrait;
use pocketmine\item\Item;
use pocketmine\math\Facing;
@@ -30,14 +31,18 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-final class FloorBanner extends BaseBanner{
+final class FloorBanner extends BaseBanner implements SignLikeRotation{
use SignLikeRotationTrait;
- protected function getSupportingFace() : int{
+ protected function getOminousVersion() : Block{
+ return VanillaBlocks::OMINOUS_BANNER()->setRotation($this->rotation);
+ }
+
+ protected function getSupportingFace() : Facing{
return Facing::DOWN;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face !== Facing::UP){
return false;
}
diff --git a/src/block/FloorCoralFan.php b/src/block/FloorCoralFan.php
index 5b74d08af..3adfe0420 100644
--- a/src/block/FloorCoralFan.php
+++ b/src/block/FloorCoralFan.php
@@ -38,16 +38,16 @@ use function rad2deg;
final class FloorCoralFan extends BaseCoral{
use StaticSupportTrait;
- private int $axis = Axis::X;
+ private Axis $axis = Axis::X;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalAxis($this->axis);
}
- public function getAxis() : int{ return $this->axis; }
+ public function getAxis() : Axis{ return $this->axis; }
/** @return $this */
- public function setAxis(int $axis) : self{
+ public function setAxis(Axis $axis) : self{
if($axis !== Axis::X && $axis !== Axis::Z){
throw new \InvalidArgumentException("Axis must be X or Z only");
}
@@ -55,7 +55,7 @@ final class FloorCoralFan extends BaseCoral{
return $this;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$playerBlockPos = $player->getPosition()->floor();
$directionVector = $blockReplace->position->subtractVector($playerBlockPos)->normalize();
diff --git a/src/block/FloorSign.php b/src/block/FloorSign.php
index 5615d15d8..3f2bd6d22 100644
--- a/src/block/FloorSign.php
+++ b/src/block/FloorSign.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\SignLikeRotation;
use pocketmine\block\utils\SignLikeRotationTrait;
use pocketmine\item\Item;
use pocketmine\math\Facing;
@@ -30,14 +31,14 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-final class FloorSign extends BaseSign{
+final class FloorSign extends BaseSign implements SignLikeRotation{
use SignLikeRotationTrait;
- protected function getSupportingFace() : int{
+ protected function getSupportingFace() : Facing{
return Facing::DOWN;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face !== Facing::UP){
return false;
}
diff --git a/src/block/Flowable.php b/src/block/Flowable.php
index 355c9caea..db1b5745b 100644
--- a/src/block/Flowable.php
+++ b/src/block/Flowable.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
/**
@@ -40,7 +41,7 @@ abstract class Flowable extends Transparent{
return false;
}
- public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
+ public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, Facing $face, bool $isClickedBlock) : bool{
return (!$this->canBeFlowedInto() || !$blockReplace instanceof Liquid) &&
parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
@@ -49,7 +50,7 @@ abstract class Flowable extends Transparent{
return [];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
}
diff --git a/src/block/FlowerPot.php b/src/block/FlowerPot.php
index 79fb73b12..88d23380b 100644
--- a/src/block/FlowerPot.php
+++ b/src/block/FlowerPot.php
@@ -84,14 +84,14 @@ class FlowerPot extends Flowable{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->contract(3 / 16, 0, 3 / 16)->trim(Facing::UP, 5 / 8)];
+ return [AxisAlignedBB::one()->contractedCopy(3 / 16, 0, 3 / 16)->trimmedCopy(Facing::UP, 5 / 8)];
}
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport();
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$world = $this->position->getWorld();
$plant = $item->getBlock();
if($this->plant !== null){
diff --git a/src/block/FrostedIce.php b/src/block/FrostedIce.php
index 3e8592306..046d75811 100644
--- a/src/block/FrostedIce.php
+++ b/src/block/FrostedIce.php
@@ -23,11 +23,12 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use function mt_rand;
-class FrostedIce extends Ice{
+class FrostedIce extends Ice implements Ageable{
use AgeableTrait;
public const MAX_AGE = 3;
diff --git a/src/block/Furnace.php b/src/block/Furnace.php
index 2c4433413..9a315dc1c 100644
--- a/src/block/Furnace.php
+++ b/src/block/Furnace.php
@@ -26,15 +26,18 @@ namespace pocketmine\block;
use pocketmine\block\inventory\window\FurnaceInventoryWindow;
use pocketmine\block\tile\Furnace as TileFurnace;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\Lightable;
use pocketmine\block\utils\LightableTrait;
use pocketmine\crafting\FurnaceType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use function mt_rand;
-class Furnace extends Opaque{
+class Furnace extends Opaque implements Lightable, HorizontalFacing{
use FacesOppositePlacingPlayerTrait;
use LightableTrait;
@@ -46,7 +49,7 @@ class Furnace extends Opaque{
}
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->lit);
}
@@ -58,7 +61,7 @@ class Furnace extends Opaque{
return $this->lit ? 13 : 0;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
$furnace = $this->position->getWorld()->getTile($this->position);
if($furnace instanceof TileFurnace && $furnace->canOpenWith($item->getCustomName())){
diff --git a/src/block/GlazedTerracotta.php b/src/block/GlazedTerracotta.php
index 15b3254e5..ccb928875 100644
--- a/src/block/GlazedTerracotta.php
+++ b/src/block/GlazedTerracotta.php
@@ -23,10 +23,12 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
-class GlazedTerracotta extends Opaque{
+class GlazedTerracotta extends Opaque implements Colored, HorizontalFacing{
use ColoredTrait;
use FacesOppositePlacingPlayerTrait;
}
diff --git a/src/block/GlowLichen.php b/src/block/GlowLichen.php
index a44c4d035..0815303a8 100644
--- a/src/block/GlowLichen.php
+++ b/src/block/GlowLichen.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
+use pocketmine\block\utils\MultiAnyFacing;
use pocketmine\block\utils\MultiAnySupportTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Fertilizer;
@@ -35,7 +36,7 @@ use pocketmine\world\World;
use function count;
use function shuffle;
-class GlowLichen extends Transparent{
+class GlowLichen extends Transparent implements MultiAnyFacing{
use MultiAnySupportTrait;
public function getLightLevel() : int{
@@ -50,7 +51,7 @@ class GlowLichen extends Transparent{
return [];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -59,13 +60,13 @@ class GlowLichen extends Transparent{
}
/**
- * @return int[]
+ * @return Facing[]
*/
protected function getInitialPlaceFaces(Block $blockReplace) : array{
return $blockReplace instanceof GlowLichen ? $blockReplace->faces : [];
}
- private function getSpreadBlock(Block $replace, int $spreadFace) : ?Block{
+ private function getSpreadBlock(Block $replace, Facing $spreadFace) : ?Block{
if($replace instanceof self && $replace->hasSameTypeId($this)){
if($replace->hasFace($spreadFace)){
return null;
@@ -80,7 +81,7 @@ class GlowLichen extends Transparent{
return $result->setFace($spreadFace, true);
}
- private function spread(World $world, Vector3 $replacePos, int $spreadFace) : bool{
+ private function spread(World $world, Vector3 $replacePos, Facing $spreadFace) : bool{
$supportBlock = $world->getBlock($replacePos->getSide($spreadFace));
$supportFace = Facing::opposite($spreadFace);
@@ -98,9 +99,9 @@ class GlowLichen extends Transparent{
}
/**
- * @phpstan-return \Generator
+ * @phpstan-return \Generator
*/
- private static function getShuffledSpreadFaces(int $sourceFace) : \Generator{
+ private static function getShuffledSpreadFaces(Facing $sourceFace) : \Generator{
$skipAxis = Facing::axis($sourceFace);
$faces = Facing::ALL;
@@ -112,7 +113,7 @@ class GlowLichen extends Transparent{
}
}
- private function spreadAroundSupport(int $sourceFace) : bool{
+ private function spreadAroundSupport(Facing $sourceFace) : bool{
$world = $this->position->getWorld();
$supportPos = $this->position->getSide($sourceFace);
@@ -126,7 +127,7 @@ class GlowLichen extends Transparent{
return false;
}
- private function spreadAdjacentToSupport(int $sourceFace) : bool{
+ private function spreadAdjacentToSupport(Facing $sourceFace) : bool{
$world = $this->position->getWorld();
foreach(self::getShuffledSpreadFaces($sourceFace) as $spreadFace){
@@ -138,7 +139,7 @@ class GlowLichen extends Transparent{
return false;
}
- private function spreadWithinSelf(int $sourceFace) : bool{
+ private function spreadWithinSelf(Facing $sourceFace) : bool{
foreach(self::getShuffledSpreadFaces($sourceFace) as $spreadFace){
if(!$this->hasFace($spreadFace) && $this->spread($this->position->getWorld(), $this->position, $spreadFace)){
return true;
@@ -148,7 +149,7 @@ class GlowLichen extends Transparent{
return false;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && count($this->faces) > 0){
$shuffledFaces = $this->faces;
shuffle($shuffledFaces);
diff --git a/src/block/Grass.php b/src/block/Grass.php
index 8a9fea8ea..d8fe435f2 100644
--- a/src/block/Grass.php
+++ b/src/block/Grass.php
@@ -81,7 +81,7 @@ class Grass extends Opaque{
}
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($this->getSide(Facing::UP)->getTypeId() !== BlockTypeIds::AIR){
return false;
}
diff --git a/src/block/GrassPath.php b/src/block/GrassPath.php
index ea56e4b95..7a5985e42 100644
--- a/src/block/GrassPath.php
+++ b/src/block/GrassPath.php
@@ -30,7 +30,7 @@ use pocketmine\math\Facing;
class GrassPath extends Transparent{
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 16)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 1 / 16)];
}
public function onNearbyBlockChange() : void{
diff --git a/src/block/HayBale.php b/src/block/HayBale.php
index 6fdd2cb63..dacfe92fa 100644
--- a/src/block/HayBale.php
+++ b/src/block/HayBale.php
@@ -23,10 +23,11 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\PillarRotation;
use pocketmine\block\utils\PillarRotationTrait;
use pocketmine\entity\Entity;
-class HayBale extends Opaque{
+class HayBale extends Opaque implements PillarRotation{
use PillarRotationTrait;
public function getFlameEncouragement() : int{
diff --git a/src/block/Hopper.php b/src/block/Hopper.php
index 8c65e836c..e0a0f6dc7 100644
--- a/src/block/Hopper.php
+++ b/src/block/Hopper.php
@@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\inventory\window\HopperInventoryWindow;
use pocketmine\block\tile\Hopper as TileHopper;
+use pocketmine\block\utils\PoweredByRedstone;
use pocketmine\block\utils\PoweredByRedstoneTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -35,20 +36,20 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-class Hopper extends Transparent{
+class Hopper extends Transparent implements PoweredByRedstone{
use PoweredByRedstoneTrait;
- private int $facing = Facing::DOWN;
+ private Facing $facing = Facing::DOWN;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->facingExcept($this->facing, Facing::UP);
$w->bool($this->powered);
}
- public function getFacing() : int{ return $this->facing; }
+ public function getFacing() : Facing{ return $this->facing; }
/** @return $this */
- public function setFacing(int $facing) : self{
+ public function setFacing(Facing $facing) : self{
if($facing === Facing::UP){
throw new \InvalidArgumentException("Hopper may not face upward");
}
@@ -58,16 +59,16 @@ class Hopper extends Transparent{
protected function recalculateCollisionBoxes() : array{
$result = [
- AxisAlignedBB::one()->trim(Facing::UP, 6 / 16) //the empty area around the bottom is currently considered solid
+ AxisAlignedBB::one()->trimmedCopy(Facing::UP, 6 / 16) //the empty area around the bottom is currently considered solid
];
foreach(Facing::HORIZONTAL as $f){ //add the frame parts around the bowl
- $result[] = AxisAlignedBB::one()->trim($f, 14 / 16);
+ $result[] = AxisAlignedBB::one()->trimmedCopy($f, 14 / 16);
}
return $result;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return match($facing){
Facing::UP => SupportType::FULL,
Facing::DOWN => $this->facing === Facing::DOWN ? SupportType::CENTER : SupportType::NONE,
@@ -75,13 +76,13 @@ class Hopper extends Transparent{
};
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->facing = $face === Facing::DOWN ? Facing::DOWN : Facing::opposite($face);
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{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileHopper){ //TODO: find a way to have inventories open on click without this boilerplate in every block
diff --git a/src/block/ItemFrame.php b/src/block/ItemFrame.php
index c03806a3b..ee0c8c452 100644
--- a/src/block/ItemFrame.php
+++ b/src/block/ItemFrame.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\tile\ItemFrame as TileItemFrame;
+use pocketmine\block\utils\AnyFacing;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -39,7 +40,7 @@ use pocketmine\world\sound\ItemFrameRotateItemSound;
use function is_infinite;
use function is_nan;
-class ItemFrame extends Flowable{
+class ItemFrame extends Flowable implements AnyFacing{
use AnyFacingTrait;
public const ROTATIONS = 8;
@@ -51,7 +52,7 @@ class ItemFrame extends Flowable{
protected float $itemDropChance = 1.0;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->facing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->hasMap);
}
@@ -131,7 +132,7 @@ class ItemFrame extends Flowable{
return $this;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($this->framedItem !== null){
$this->itemRotation = ($this->itemRotation + 1) % self::ROTATIONS;
@@ -149,7 +150,7 @@ class ItemFrame extends Flowable{
return true;
}
- public function onAttack(Item $item, int $face, ?Player $player = null) : bool{
+ public function onAttack(Item $item, Facing $face, ?Player $player = null) : bool{
if($this->framedItem === null){
return false;
}
@@ -163,7 +164,7 @@ class ItemFrame extends Flowable{
return true;
}
- private function canBeSupportedAt(Block $block, int $face) : bool{
+ private function canBeSupportedAt(Block $block, Facing $face) : bool{
return $block->getAdjacentSupportType($face) !== SupportType::NONE;
}
@@ -173,7 +174,7 @@ class ItemFrame extends Flowable{
}
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
diff --git a/src/block/Jukebox.php b/src/block/Jukebox.php
index a61dd06db..d2f39c7d7 100644
--- a/src/block/Jukebox.php
+++ b/src/block/Jukebox.php
@@ -27,6 +27,7 @@ use pocketmine\block\tile\Jukebox as JukeboxTile;
use pocketmine\item\Item;
use pocketmine\item\Record;
use pocketmine\lang\KnownTranslationFactory;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\RecordSound;
@@ -40,7 +41,7 @@ class Jukebox extends Opaque{
return 300;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
if($this->record !== null){
$this->ejectRecord();
diff --git a/src/block/Ladder.php b/src/block/Ladder.php
index 09c0b8f6b..03c9ea57f 100644
--- a/src/block/Ladder.php
+++ b/src/block/Ladder.php
@@ -23,19 +23,20 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
use pocketmine\item\Item;
-use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-class Ladder extends Transparent{
+class Ladder extends Transparent implements HorizontalFacing{
use HorizontalFacingTrait;
public function hasEntityCollision() : bool{
@@ -59,16 +60,16 @@ class Ladder extends Transparent{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim($this->facing, 13 / 16)];
+ return [AxisAlignedBB::one()->trimmedCopy($this->facing->toFacing(), 13 / 16)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
- if($this->canBeSupportedAt($blockReplace, Facing::opposite($face)) && Facing::axis($face) !== Axis::Y){
- $this->facing = $face;
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ if(($hzFacing = HorizontalFacingOption::tryFromFacing($face)) !== null && $this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
+ $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@@ -76,12 +77,12 @@ class Ladder extends Transparent{
}
public function onNearbyBlockChange() : void{
- if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){ //Replace with common break method
+ if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing->toFacing()))){ //Replace with common break method
$this->position->getWorld()->useBreakOn($this->position);
}
}
- private function canBeSupportedAt(Block $block, int $face) : bool{
+ private function canBeSupportedAt(Block $block, Facing $face) : bool{
return $block->getAdjacentSupportType($face) === SupportType::FULL;
}
}
diff --git a/src/block/Lantern.php b/src/block/Lantern.php
index 302e69fd7..02e310768 100644
--- a/src/block/Lantern.php
+++ b/src/block/Lantern.php
@@ -62,18 +62,18 @@ class Lantern extends Transparent{
protected function recalculateCollisionBoxes() : array{
return [
AxisAlignedBB::one()
- ->trim(Facing::UP, $this->hanging ? 6 / 16 : 8 / 16)
- ->trim(Facing::DOWN, $this->hanging ? 2 / 16 : 0)
- ->squash(Axis::X, 5 / 16)
- ->squash(Axis::Z, 5 / 16)
+ ->trimmedCopy(Facing::UP, $this->hanging ? 6 / 16 : 8 / 16)
+ ->trimmedCopy(Facing::DOWN, $this->hanging ? 2 / 16 : 0)
+ ->squashedCopy(Axis::X, 5 / 16)
+ ->squashedCopy(Axis::Z, 5 / 16)
];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$downSupport = $this->canBeSupportedAt($blockReplace, Facing::DOWN);
if(!$downSupport && !$this->canBeSupportedAt($blockReplace, Facing::UP)){
return false;
@@ -90,7 +90,7 @@ class Lantern extends Transparent{
}
}
- private function canBeSupportedAt(Block $block, int $face) : bool{
+ private function canBeSupportedAt(Block $block, Facing $face) : bool{
return $block->getAdjacentSupportType($face)->hasCenterSupport();
}
}
diff --git a/src/block/LavaCauldron.php b/src/block/LavaCauldron.php
index 3df903e22..f89addd78 100644
--- a/src/block/LavaCauldron.php
+++ b/src/block/LavaCauldron.php
@@ -31,6 +31,7 @@ use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds;
use pocketmine\item\VanillaItems;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\CauldronEmptyLavaSound;
@@ -61,7 +62,7 @@ final class LavaCauldron extends FillableCauldron{
return new CauldronEmptyLavaSound();
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
match($item->getTypeId()){
ItemTypeIds::BUCKET => $this->removeFillLevels(self::MAX_FILL_LEVEL, $item, VanillaItems::LAVA_BUCKET(), $returnedItems),
ItemTypeIds::POWDER_SNOW_BUCKET, ItemTypeIds::WATER_BUCKET => $this->mix($item, VanillaItems::BUCKET(), $returnedItems),
diff --git a/src/block/Leaves.php b/src/block/Leaves.php
index 847536557..8ed99b411 100644
--- a/src/block/Leaves.php
+++ b/src/block/Leaves.php
@@ -134,7 +134,7 @@ class Leaves extends Transparent{
}
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->noDecay = true; //artificial leaves don't decay
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@@ -188,7 +188,7 @@ class Leaves extends Transparent{
return 60;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
}
diff --git a/src/block/Lectern.php b/src/block/Lectern.php
index 03880b3c5..43c28f32b 100644
--- a/src/block/Lectern.php
+++ b/src/block/Lectern.php
@@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\Lectern as TileLectern;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
@@ -36,7 +37,7 @@ use pocketmine\player\Player;
use pocketmine\world\sound\LecternPlaceBookSound;
use function count;
-class Lectern extends Transparent{
+class Lectern extends Transparent implements HorizontalFacing{
use FacesOppositePlacingPlayerTrait;
protected int $viewedPage = 0;
@@ -45,7 +46,7 @@ class Lectern extends Transparent{
protected bool $producingSignal = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->producingSignal);
}
@@ -83,10 +84,10 @@ class Lectern extends Transparent{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 0.1)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 0.1)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -119,7 +120,7 @@ class Lectern extends Transparent{
return $this;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($this->book === null && $item instanceof WritableBookBase){
$world = $this->position->getWorld();
$world->setBlock($this->position, $this->setBook($item));
@@ -129,7 +130,7 @@ class Lectern extends Transparent{
return true;
}
- public function onAttack(Item $item, int $face, ?Player $player = null) : bool{
+ public function onAttack(Item $item, Facing $face, ?Player $player = null) : bool{
if($this->book !== null){
$world = $this->position->getWorld();
$world->dropItem($this->position->up(), $this->book);
diff --git a/src/block/Lever.php b/src/block/Lever.php
index d2b98efc3..24bbfc502 100644
--- a/src/block/Lever.php
+++ b/src/block/Lever.php
@@ -30,7 +30,6 @@ use pocketmine\math\Axis;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
-use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\RedstonePowerOffSound;
use pocketmine\world\sound\RedstonePowerOnSound;
@@ -60,7 +59,7 @@ class Lever extends Flowable{
return $this;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
@@ -78,7 +77,6 @@ class Lever extends Flowable{
Facing::SOUTH => LeverFacing::SOUTH,
Facing::WEST => LeverFacing::WEST,
Facing::EAST => LeverFacing::EAST,
- default => throw new AssumptionFailedError("Bad facing value"),
};
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
@@ -90,7 +88,7 @@ class Lever extends Flowable{
}
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$this->activated = !$this->activated;
$world = $this->position->getWorld();
$world->setBlock($this->position, $this);
@@ -101,7 +99,7 @@ class Lever extends Flowable{
return true;
}
- private function canBeSupportedAt(Block $block, int $face) : bool{
+ private function canBeSupportedAt(Block $block, Facing $face) : bool{
return $block->getAdjacentSupportType($face)->hasCenterSupport();
}
diff --git a/src/block/Light.php b/src/block/Light.php
index 29a3a8dfc..27bfbeab4 100644
--- a/src/block/Light.php
+++ b/src/block/Light.php
@@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
@@ -51,12 +52,12 @@ final class Light extends Flowable{
public function canBeReplaced() : bool{ return true; }
- public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
+ public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, Facing $face, bool $isClickedBlock) : bool{
//light blocks behave like solid blocks when placing them on another light block
return $blockReplace->canBeReplaced() && $blockReplace->getTypeId() !== $this->getTypeId();
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$this->level = $this->level === self::MAX_LIGHT_LEVEL ?
self::MIN_LIGHT_LEVEL :
$this->level + 1;
diff --git a/src/block/LightningRod.php b/src/block/LightningRod.php
index a0dd50542..f26f8212d 100644
--- a/src/block/LightningRod.php
+++ b/src/block/LightningRod.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\AnyFacing;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\item\Item;
use pocketmine\math\Axis;
@@ -32,7 +33,7 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-final class LightningRod extends Transparent{
+final class LightningRod extends Transparent implements AnyFacing{
use AnyFacingTrait;
protected function recalculateCollisionBoxes() : array{
@@ -41,14 +42,14 @@ final class LightningRod extends Transparent{
$result = AxisAlignedBB::one();
foreach([Axis::X, Axis::Y, Axis::Z] as $axis){
if($axis !== $myAxis){
- $result->squash($axis, 6 / 16);
+ $result = $result->squashedCopy($axis, 6 / 16);
}
}
return [$result];
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
diff --git a/src/block/Liquid.php b/src/block/Liquid.php
index 813d76904..d47e21035 100644
--- a/src/block/Liquid.php
+++ b/src/block/Liquid.php
@@ -92,7 +92,7 @@ abstract class Liquid extends Transparent{
return [];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -170,7 +170,7 @@ abstract class Liquid extends Transparent{
$world = $this->position->getWorld();
foreach(Facing::HORIZONTAL as $j){
- [$dx, $dy, $dz] = Facing::OFFSET[$j];
+ [$dx, $dy, $dz] = Facing::OFFSET[$j->value];
$sideX = $x + $dx;
$sideY = $y + $dy;
@@ -206,7 +206,7 @@ abstract class Liquid extends Transparent{
if($this->falling){
foreach(Facing::HORIZONTAL as $facing){
- [$dx, $dy, $dz] = Facing::OFFSET[$facing];
+ [$dx, $dy, $dz] = Facing::OFFSET[$facing->value];
if(
!$this->canFlowInto($world->getBlockAt($x + $dx, $y + $dy, $z + $dz)) ||
!$this->canFlowInto($world->getBlockAt($x + $dx, $y + $dy + 1, $z + $dz))
diff --git a/src/block/Loom.php b/src/block/Loom.php
index d19fc9449..3c7cf2cc8 100644
--- a/src/block/Loom.php
+++ b/src/block/Loom.php
@@ -25,14 +25,16 @@ namespace pocketmine\block;
use pocketmine\block\inventory\window\LoomInventoryWindow;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
-final class Loom extends Opaque{
+final class Loom extends Opaque implements HorizontalFacing{
use FacesOppositePlacingPlayerTrait;
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){
$player->setCurrentWindow(new LoomInventoryWindow($player, $this->position));
return true;
diff --git a/src/block/MobHead.php b/src/block/MobHead.php
index 41e816c55..a943a9a98 100644
--- a/src/block/MobHead.php
+++ b/src/block/MobHead.php
@@ -41,7 +41,7 @@ class MobHead extends Flowable{
protected MobHeadType $mobHeadType = MobHeadType::SKELETON;
- protected int $facing = Facing::NORTH;
+ protected Facing $facing = Facing::NORTH;
protected int $rotation = self::MIN_ROTATION; //TODO: split this into floor skull and wall skull handling
public function describeBlockItemState(RuntimeDataDescriber $w) : void{
@@ -82,10 +82,10 @@ class MobHead extends Flowable{
return $this;
}
- public function getFacing() : int{ return $this->facing; }
+ public function getFacing() : Facing{ return $this->facing; }
/** @return $this */
- public function setFacing(int $facing) : self{
+ public function setFacing(Facing $facing) : self{
if($facing === Facing::DOWN){
throw new \InvalidArgumentException("Skull may not face DOWN");
}
@@ -106,17 +106,17 @@ class MobHead extends Flowable{
protected function recalculateCollisionBoxes() : array{
$collisionBox = AxisAlignedBB::one()
- ->contract(0.25, 0, 0.25)
- ->trim(Facing::UP, 0.5);
+ ->contractedCopy(0.25, 0, 0.25)
+ ->trimmedCopy(Facing::UP, 0.5);
if($this->facing !== Facing::UP){
$collisionBox = $collisionBox
- ->offsetTowards(Facing::opposite($this->facing), 0.25)
- ->offsetTowards(Facing::UP, 0.25);
+ ->offsetTowardsCopy(Facing::opposite($this->facing), 0.25)
+ ->offsetTowardsCopy(Facing::UP, 0.25);
}
return [$collisionBox];
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::DOWN){
return false;
}
diff --git a/src/block/MonsterSpawner.php b/src/block/MonsterSpawner.php
index 5cbe80e0a..c11327507 100644
--- a/src/block/MonsterSpawner.php
+++ b/src/block/MonsterSpawner.php
@@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use function mt_rand;
class MonsterSpawner extends Transparent{
@@ -41,7 +42,7 @@ class MonsterSpawner extends Transparent{
//TODO
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
}
diff --git a/src/block/NetherPortal.php b/src/block/NetherPortal.php
index 1b199c603..2f00b44f2 100644
--- a/src/block/NetherPortal.php
+++ b/src/block/NetherPortal.php
@@ -28,16 +28,17 @@ use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\item\Item;
use pocketmine\math\Axis;
+use pocketmine\math\Facing;
class NetherPortal extends Transparent{
- protected int $axis = Axis::X;
+ protected Axis $axis = Axis::X;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalAxis($this->axis);
}
- public function getAxis() : int{
+ public function getAxis() : Axis{
return $this->axis;
}
@@ -45,7 +46,7 @@ class NetherPortal extends Transparent{
* @throws \InvalidArgumentException
* @return $this
*/
- public function setAxis(int $axis) : self{
+ public function setAxis(Axis $axis) : self{
if($axis !== Axis::X && $axis !== Axis::Z){
throw new \InvalidArgumentException("Invalid axis");
}
@@ -65,7 +66,7 @@ class NetherPortal extends Transparent{
return [];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
diff --git a/src/block/NetherVines.php b/src/block/NetherVines.php
index e8729c00f..98464ed58 100644
--- a/src/block/NetherVines.php
+++ b/src/block/NetherVines.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\block\utils\StaticSupportTrait;
@@ -41,16 +42,16 @@ use function mt_rand;
/**
* This class is used for Weeping & Twisting vines, because they have same behaviour
*/
-class NetherVines extends Flowable{
+class NetherVines extends Flowable implements Ageable{
use AgeableTrait;
use StaticSupportTrait;
public const MAX_AGE = 25;
/** Direction the vine grows towards. */
- private int $growthFace;
+ private Facing $growthFace;
- public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo, int $growthFace){
+ public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo, Facing $growthFace){
$this->growthFace = $growthFace;
parent::__construct($idInfo, $name, $typeInfo);
}
@@ -79,12 +80,12 @@ class NetherVines extends Flowable{
return $top;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->age = mt_rand(0, self::MAX_AGE - 1);
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{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer){
if($this->grow($player, mt_rand(1, 5))){
$item->pop();
@@ -158,7 +159,7 @@ class NetherVines extends Flowable{
return [];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
}
diff --git a/src/block/NetherWartPlant.php b/src/block/NetherWartPlant.php
index 34e6fd57e..df0609754 100644
--- a/src/block/NetherWartPlant.php
+++ b/src/block/NetherWartPlant.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\FortuneDropHelper;
@@ -31,7 +32,7 @@ use pocketmine\item\Item;
use pocketmine\math\Facing;
use function mt_rand;
-class NetherWartPlant extends Flowable{
+class NetherWartPlant extends Flowable implements Ageable{
use AgeableTrait;
use StaticSupportTrait;
diff --git a/src/block/OminousFloorBanner.php b/src/block/OminousFloorBanner.php
new file mode 100644
index 000000000..f4a03664f
--- /dev/null
+++ b/src/block/OminousFloorBanner.php
@@ -0,0 +1,53 @@
+rotation = self::getRotationFromYaw($player->getLocation()->getYaw());
+ }
+ return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
+ }
+}
diff --git a/src/block/OminousWallBanner.php b/src/block/OminousWallBanner.php
new file mode 100644
index 000000000..78b9e9024
--- /dev/null
+++ b/src/block/OminousWallBanner.php
@@ -0,0 +1,50 @@
+facing->toFacing());
+ }
+
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ $hzFacing = HorizontalFacingOption::tryFromFacing($face);
+ if($hzFacing === null){
+ return false;
+ }
+ $this->facing = $hzFacing;
+ return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
+ }
+}
diff --git a/src/block/PinkPetals.php b/src/block/PinkPetals.php
index 17bc4c50a..d772d5df8 100644
--- a/src/block/PinkPetals.php
+++ b/src/block/PinkPetals.php
@@ -24,6 +24,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\StaticSupportTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -34,7 +36,7 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-class PinkPetals extends Flowable{
+class PinkPetals extends Flowable implements HorizontalFacing{
use HorizontalFacingTrait;
use StaticSupportTrait {
canBePlacedAt as supportedWhenPlacedAt;
@@ -46,7 +48,7 @@ class PinkPetals extends Flowable{
protected int $count = self::MIN_COUNT;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->boundedIntAuto(self::MIN_COUNT, self::MAX_COUNT, $this->count);
}
@@ -69,21 +71,21 @@ class PinkPetals extends Flowable{
return $supportBlock->hasTypeTag(BlockTypeTags::DIRT) || $supportBlock->hasTypeTag(BlockTypeTags::MUD);
}
- public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
+ public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, Facing $face, bool $isClickedBlock) : bool{
return ($blockReplace instanceof PinkPetals && $blockReplace->count < self::MAX_COUNT) || $this->supportedWhenPlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockReplace instanceof PinkPetals && $blockReplace->count < self::MAX_COUNT){
$this->count = $blockReplace->count + 1;
$this->facing = $blockReplace->facing;
}elseif($player !== null){
- $this->facing = Facing::opposite($player->getHorizontalFacing());
+ $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer){
$grew = false;
if($this->count < self::MAX_COUNT){
diff --git a/src/block/PitcherCrop.php b/src/block/PitcherCrop.php
index d41aed284..7223dc66d 100644
--- a/src/block/PitcherCrop.php
+++ b/src/block/PitcherCrop.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\CropGrowthHelper;
@@ -38,7 +39,7 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-final class PitcherCrop extends Flowable{
+final class PitcherCrop extends Flowable implements Ageable{
use AgeableTrait;
use StaticSupportTrait;
@@ -53,10 +54,10 @@ final class PitcherCrop extends Flowable{
$heightTrim = $this->age === 0 ? 13 : 11;
return [
AxisAlignedBB::one()
- ->trim(Facing::UP, $heightTrim / 16)
- ->squash(Axis::X, $widthTrim / 16)
- ->squash(Axis::Z, $widthTrim / 16)
- ->extend(Facing::DOWN, 1 / 16) //presumably this is to correct for farmland being 15/16 of a block tall
+ ->trimmedCopy(Facing::UP, $heightTrim / 16)
+ ->squashedCopy(Axis::X, $widthTrim / 16)
+ ->squashedCopy(Axis::Z, $widthTrim / 16)
+ ->extendedCopy(Facing::DOWN, 1 / 16) //presumably this is to correct for farmland being 15/16 of a block tall
];
}
@@ -84,7 +85,7 @@ final class PitcherCrop extends Flowable{
return BlockEventHelper::grow($this, (clone $this)->setAge($this->age + 1), $player);
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
return true;
diff --git a/src/block/Planks.php b/src/block/Planks.php
index 1074f8adf..ad7956361 100644
--- a/src/block/Planks.php
+++ b/src/block/Planks.php
@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodTypeTrait;
-class Planks extends Opaque{
+class Planks extends Opaque implements WoodMaterial{
use WoodTypeTrait;
public function getFuelTime() : int{
diff --git a/src/block/PotionCauldron.php b/src/block/PotionCauldron.php
index ca91664e4..92a5507ee 100644
--- a/src/block/PotionCauldron.php
+++ b/src/block/PotionCauldron.php
@@ -27,6 +27,7 @@ use pocketmine\block\tile\Cauldron as TileCauldron;
use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds;
use pocketmine\item\VanillaItems;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\CauldronEmptyPotionSound;
@@ -94,7 +95,7 @@ final class PotionCauldron extends FillableCauldron{
}
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
match($item->getTypeId()){
ItemTypeIds::LINGERING_POTION, ItemTypeIds::POTION, ItemTypeIds::SPLASH_POTION => $this->addFillLevelsOrMix(self::POTION_FILL_AMOUNT, $item, VanillaItems::GLASS_BOTTLE(), $returnedItems),
ItemTypeIds::GLASS_BOTTLE => $this->potionItem === null ? null : $this->removeFillLevels(self::POTION_FILL_AMOUNT, $item, clone $this->potionItem, $returnedItems),
diff --git a/src/block/PoweredRail.php b/src/block/PoweredRail.php
index 25d6dc9e3..321b19a46 100644
--- a/src/block/PoweredRail.php
+++ b/src/block/PoweredRail.php
@@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\PoweredByRedstone;
use pocketmine\block\utils\RailPoweredByRedstoneTrait;
-class PoweredRail extends StraightOnlyRail{
+class PoweredRail extends StraightOnlyRail implements PoweredByRedstone{
use RailPoweredByRedstoneTrait;
}
diff --git a/src/block/PressurePlate.php b/src/block/PressurePlate.php
index 1dd4b50d9..b96154a15 100644
--- a/src/block/PressurePlate.php
+++ b/src/block/PressurePlate.php
@@ -57,7 +57,7 @@ abstract class PressurePlate extends Transparent{
return [];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -83,10 +83,10 @@ abstract class PressurePlate extends Transparent{
*/
protected function getActivationBox() : AxisAlignedBB{
return AxisAlignedBB::one()
- ->squash(Axis::X, 1 / 8)
- ->squash(Axis::Z, 1 / 8)
- ->trim(Facing::UP, 3 / 4)
- ->offset($this->position->x, $this->position->y, $this->position->z);
+ ->squashedCopy(Axis::X, 1 / 8)
+ ->squashedCopy(Axis::Z, 1 / 8)
+ ->trimmedCopy(Facing::UP, 3 / 4)
+ ->offsetCopy($this->position->x, $this->position->y, $this->position->z);
}
/**
diff --git a/src/block/Pumpkin.php b/src/block/Pumpkin.php
index 1b7f6a9cd..668b10b98 100644
--- a/src/block/Pumpkin.php
+++ b/src/block/Pumpkin.php
@@ -23,21 +23,21 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\item\Item;
use pocketmine\item\Shears;
use pocketmine\item\VanillaItems;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
-use function in_array;
class Pumpkin extends Opaque{
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
- if($item instanceof Shears && in_array($face, Facing::HORIZONTAL, true)){
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ if($item instanceof Shears && ($hzFacing = HorizontalFacingOption::tryFromFacing($face)) !== null){
$item->applyDamage(1);
$world = $this->position->getWorld();
- $world->setBlock($this->position, VanillaBlocks::CARVED_PUMPKIN()->setFacing($face));
+ $world->setBlock($this->position, VanillaBlocks::CARVED_PUMPKIN()->setFacing($hzFacing));
$world->dropItem($this->position->add(0.5, 0.5, 0.5), VanillaItems::PUMPKIN_SEEDS()->setCount(1));
return true;
}
diff --git a/src/block/Rail.php b/src/block/Rail.php
index f516902f0..f904c238d 100644
--- a/src/block/Rail.php
+++ b/src/block/Rail.php
@@ -24,18 +24,16 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\RailConnectionInfo;
-use pocketmine\data\bedrock\block\BlockLegacyMetadata;
+use pocketmine\block\utils\RailShape;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\math\Facing;
-use function array_keys;
-use function implode;
class Rail extends BaseRail{
- private int $railShape = BlockLegacyMetadata::RAIL_STRAIGHT_NORTH_SOUTH;
+ private RailShape $railShape = RailShape::FLAT_AXIS_Z;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->railShape($this->railShape);
+ $w->enum($this->railShape);
}
protected function setShapeFromConnections(array $connections) : void{
@@ -43,11 +41,11 @@ class Rail extends BaseRail{
if($railShape === null){
throw new \InvalidArgumentException("No rail shape matches these connections");
}
- $this->railShape = $railShape;
+ $this->railShape = RailShape::from($railShape);
}
protected function getCurrentShapeConnections() : array{
- return RailConnectionInfo::CURVE_CONNECTIONS[$this->railShape] ?? RailConnectionInfo::CONNECTIONS[$this->railShape];
+ return RailConnectionInfo::CURVE_CONNECTIONS[$this->railShape->value] ?? RailConnectionInfo::CONNECTIONS[$this->railShape->value];
}
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
@@ -60,8 +58,8 @@ class Rail extends BaseRail{
Facing::WEST,
Facing::EAST
] as $d){
- if($constraint !== $d){
- $possible[$d] = true;
+ if($constraint !== $d->value){
+ $possible[$d->value] = true;
}
}
}
@@ -69,13 +67,10 @@ class Rail extends BaseRail{
return $possible;
}
- public function getShape() : int{ return $this->railShape; }
+ public function getShape() : RailShape{ return $this->railShape; }
/** @return $this */
- public function setShape(int $shape) : self{
- if(!isset(RailConnectionInfo::CONNECTIONS[$shape]) && !isset(RailConnectionInfo::CURVE_CONNECTIONS[$shape])){
- throw new \InvalidArgumentException("Invalid shape, must be one of " . implode(", ", [...array_keys(RailConnectionInfo::CONNECTIONS), ...array_keys(RailConnectionInfo::CURVE_CONNECTIONS)]));
- }
+ public function setShape(RailShape $shape) : self{
$this->railShape = $shape;
return $this;
}
diff --git a/src/block/RedMushroom.php b/src/block/RedMushroom.php
index 81ab940f5..a012fd4c7 100644
--- a/src/block/RedMushroom.php
+++ b/src/block/RedMushroom.php
@@ -41,7 +41,7 @@ class RedMushroom extends Flowable{
}
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $this->getSide(Facing::DOWN);
$position = $this->position;
$lightLevel = $position->getWorld()->getFullLightAt($position->x, $position->y, $position->z);
diff --git a/src/block/RedstoneComparator.php b/src/block/RedstoneComparator.php
index 40e1ef510..ad00fc8b3 100644
--- a/src/block/RedstoneComparator.php
+++ b/src/block/RedstoneComparator.php
@@ -24,8 +24,11 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\tile\Comparator;
+use pocketmine\block\utils\AnalogRedstoneSignalEmitter;
use pocketmine\block\utils\AnalogRedstoneSignalEmitterTrait;
-use pocketmine\block\utils\HorizontalFacingTrait;
+use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\PoweredByRedstone;
use pocketmine\block\utils\PoweredByRedstoneTrait;
use pocketmine\block\utils\StaticSupportTrait;
use pocketmine\block\utils\SupportType;
@@ -35,11 +38,10 @@ use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
-use pocketmine\world\BlockTransaction;
use function assert;
-class RedstoneComparator extends Flowable{
- use HorizontalFacingTrait;
+class RedstoneComparator extends Flowable implements AnalogRedstoneSignalEmitter, PoweredByRedstone, HorizontalFacing{
+ use FacesOppositePlacingPlayerTrait;
use AnalogRedstoneSignalEmitterTrait;
use PoweredByRedstoneTrait;
use StaticSupportTrait;
@@ -47,7 +49,7 @@ class RedstoneComparator extends Flowable{
protected bool $isSubtractMode = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->isSubtractMode);
$w->bool($this->powered);
}
@@ -80,17 +82,10 @@ class RedstoneComparator extends Flowable{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 8)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 7 / 8)];
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
- if($player !== null){
- $this->facing = Facing::opposite($player->getHorizontalFacing());
- }
- return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
- }
-
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$this->isSubtractMode = !$this->isSubtractMode;
$this->position->getWorld()->setBlock($this->position, $this);
return true;
diff --git a/src/block/RedstoneLamp.php b/src/block/RedstoneLamp.php
index 58098c395..530fa2410 100644
--- a/src/block/RedstoneLamp.php
+++ b/src/block/RedstoneLamp.php
@@ -23,10 +23,12 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Lightable;
+use pocketmine\block\utils\PoweredByRedstone;
use pocketmine\block\utils\PoweredByRedstoneTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
-class RedstoneLamp extends Opaque{
+class RedstoneLamp extends Opaque implements PoweredByRedstone, Lightable{
use PoweredByRedstoneTrait;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
@@ -36,4 +38,14 @@ class RedstoneLamp extends Opaque{
public function getLightLevel() : int{
return $this->powered ? 15 : 0;
}
+
+ public function isLit() : bool{
+ return $this->powered;
+ }
+
+ /** @return $this */
+ public function setLit(bool $lit = true) : self{
+ $this->powered = $lit;
+ return $this;
+ }
}
diff --git a/src/block/RedstoneOre.php b/src/block/RedstoneOre.php
index 10e701a6f..52a5f5432 100644
--- a/src/block/RedstoneOre.php
+++ b/src/block/RedstoneOre.php
@@ -24,21 +24,23 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
+use pocketmine\block\utils\Lightable;
use pocketmine\block\utils\LightableTrait;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use function mt_rand;
-class RedstoneOre extends Opaque{
+class RedstoneOre extends Opaque implements Lightable{
use LightableTrait;
public function getLightLevel() : int{
return $this->lit ? 9 : 0;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if(!$this->lit){
$this->lit = true;
$this->position->getWorld()->setBlock($this->position, $this); //no return here - this shouldn't prevent block placement
diff --git a/src/block/RedstoneRepeater.php b/src/block/RedstoneRepeater.php
index bf9d0c5da..1b9ee249b 100644
--- a/src/block/RedstoneRepeater.php
+++ b/src/block/RedstoneRepeater.php
@@ -23,7 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
-use pocketmine\block\utils\HorizontalFacingTrait;
+use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\PoweredByRedstone;
use pocketmine\block\utils\PoweredByRedstoneTrait;
use pocketmine\block\utils\StaticSupportTrait;
use pocketmine\block\utils\SupportType;
@@ -33,10 +35,9 @@ use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
-use pocketmine\world\BlockTransaction;
-class RedstoneRepeater extends Flowable{
- use HorizontalFacingTrait;
+class RedstoneRepeater extends Flowable implements PoweredByRedstone, HorizontalFacing{
+ use FacesOppositePlacingPlayerTrait;
use PoweredByRedstoneTrait;
use StaticSupportTrait;
@@ -46,7 +47,7 @@ class RedstoneRepeater extends Flowable{
protected int $delay = self::MIN_DELAY;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->boundedIntAuto(self::MIN_DELAY, self::MAX_DELAY, $this->delay);
$w->bool($this->powered);
}
@@ -63,18 +64,10 @@ class RedstoneRepeater extends Flowable{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 8)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 7 / 8)];
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
- if($player !== null){
- $this->facing = Facing::opposite($player->getHorizontalFacing());
- }
-
- return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
- }
-
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if(++$this->delay > self::MAX_DELAY){
$this->delay = self::MIN_DELAY;
}
diff --git a/src/block/RedstoneTorch.php b/src/block/RedstoneTorch.php
index 26c86038b..f73076ccc 100644
--- a/src/block/RedstoneTorch.php
+++ b/src/block/RedstoneTorch.php
@@ -23,10 +23,11 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Lightable;
use pocketmine\block\utils\LightableTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
-class RedstoneTorch extends Torch{
+class RedstoneTorch extends Torch implements Lightable{
use LightableTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
diff --git a/src/block/RedstoneWire.php b/src/block/RedstoneWire.php
index a2d293fca..6be27bcb4 100644
--- a/src/block/RedstoneWire.php
+++ b/src/block/RedstoneWire.php
@@ -23,13 +23,14 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\AnalogRedstoneSignalEmitter;
use pocketmine\block\utils\AnalogRedstoneSignalEmitterTrait;
use pocketmine\block\utils\StaticSupportTrait;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Facing;
-class RedstoneWire extends Flowable{
+class RedstoneWire extends Flowable implements AnalogRedstoneSignalEmitter{
use AnalogRedstoneSignalEmitterTrait;
use StaticSupportTrait;
diff --git a/src/block/ResinClump.php b/src/block/ResinClump.php
index 75126edf3..044128cf8 100644
--- a/src/block/ResinClump.php
+++ b/src/block/ResinClump.php
@@ -23,17 +23,19 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\MultiAnyFacing;
use pocketmine\block\utils\MultiAnySupportTrait;
use pocketmine\block\utils\SupportType;
+use pocketmine\math\Facing;
-final class ResinClump extends Transparent{
+final class ResinClump extends Transparent implements MultiAnyFacing{
use MultiAnySupportTrait;
public function isSolid() : bool{
return false;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
@@ -42,7 +44,7 @@ final class ResinClump extends Transparent{
}
/**
- * @return int[]
+ * @return Facing[]
*/
protected function getInitialPlaceFaces(Block $blockReplace) : array{
return $blockReplace instanceof ResinClump ? $blockReplace->faces : [];
diff --git a/src/block/RespawnAnchor.php b/src/block/RespawnAnchor.php
new file mode 100644
index 000000000..b57d851fe
--- /dev/null
+++ b/src/block/RespawnAnchor.php
@@ -0,0 +1,124 @@
+boundedIntAuto(self::MIN_CHARGES, self::MAX_CHARGES, $this->charges);
+ }
+
+ public function getCharges() : int{
+ return $this->charges;
+ }
+
+ /** @return $this */
+ public function setCharges(int $charges) : self{
+ if($charges < self::MIN_CHARGES || $charges > self::MAX_CHARGES){
+ throw new \InvalidArgumentException("Charges must be between " . self::MIN_CHARGES . " and " . self::MAX_CHARGES . ", given: $charges");
+ }
+ $this->charges = $charges;
+ return $this;
+ }
+
+ public function getLightLevel() : int{
+ return $this->charges > 0 ? ($this->charges * 4) - 1 : 0;
+ }
+
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ if($item->getTypeId() === ItemTypeIds::fromBlockTypeId(BlockTypeIds::GLOWSTONE) && $this->charges < self::MAX_CHARGES){
+ $this->position->getWorld()->setBlock($this->position, $this->setCharges($this->charges + 1));
+ $this->position->getWorld()->addSound($this->position, new RespawnAnchorChargeSound());
+ return true;
+ }
+
+ if($this->charges > self::MIN_CHARGES){
+ if($player === null){
+ return false;
+ }
+
+ $ev = new PlayerRespawnAnchorUseEvent($player, $this, PlayerRespawnAnchorUseEvent::ACTION_EXPLODE);
+ $ev->call();
+ if($ev->isCancelled()){
+ return false;
+ }
+
+ switch($ev->getAction()){
+ case PlayerRespawnAnchorUseEvent::ACTION_EXPLODE:
+ $this->explode($player);
+ return true;
+
+ case PlayerRespawnAnchorUseEvent::ACTION_SET_SPAWN:
+ if($player->getSpawn() !== null && $player->getSpawn()->equals($this->position)){
+ return true;
+ }
+
+ $player->setSpawn($this->position);
+ $this->position->getWorld()->addSound($this->position, new RespawnAnchorSetSpawnSound());
+ $player->sendMessage(KnownTranslationFactory::tile_respawn_anchor_respawnSet()->prefix(TextFormat::GRAY));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private function explode(?Player $player) : void{
+ $ev = new BlockPreExplodeEvent($this, 5, $player);
+ $ev->setIncendiary(true);
+
+ $ev->call();
+ if($ev->isCancelled()){
+ return;
+ }
+
+ $this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
+
+ $explosion = new Explosion(Position::fromObject($this->position->add(0.5, 0.5, 0.5), $this->position->getWorld()), $ev->getRadius(), $this);
+ $explosion->setFireChance($ev->getFireChance());
+
+ if($ev->isBlockBreaking()){
+ $explosion->explodeA();
+ }
+ $explosion->explodeB();
+ }
+}
diff --git a/src/block/Sapling.php b/src/block/Sapling.php
index b3fdf59af..313d8b7d4 100644
--- a/src/block/Sapling.php
+++ b/src/block/Sapling.php
@@ -65,7 +65,7 @@ class Sapling extends Flowable{
return $supportBlock->hasTypeTag(BlockTypeTags::DIRT) || $supportBlock->hasTypeTag(BlockTypeTags::MUD);
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
diff --git a/src/block/SeaPickle.php b/src/block/SeaPickle.php
index 34f5c3e9e..51d450645 100644
--- a/src/block/SeaPickle.php
+++ b/src/block/SeaPickle.php
@@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
@@ -73,16 +74,16 @@ class SeaPickle extends Transparent{
return [];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
- public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
+ public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, Facing $face, bool $isClickedBlock) : bool{
//TODO: proper placement logic (needs a supporting face below)
return ($blockReplace instanceof SeaPickle && $blockReplace->count < self::MAX_COUNT) || parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->underwater = false; //TODO: implement this once we have new water logic in place
if($blockReplace instanceof SeaPickle && $blockReplace->count < self::MAX_COUNT){
$this->count = $blockReplace->count + 1;
@@ -91,7 +92,7 @@ class SeaPickle extends Transparent{
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{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
//TODO: bonemeal logic (requires coral)
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
}
diff --git a/src/block/ShulkerBox.php b/src/block/ShulkerBox.php
index 170033963..c29999992 100644
--- a/src/block/ShulkerBox.php
+++ b/src/block/ShulkerBox.php
@@ -27,10 +27,12 @@ use pocketmine\block\inventory\window\BlockInventoryWindow;
use pocketmine\block\tile\ShulkerBox as TileShulkerBox;
use pocketmine\block\utils\AnimatedContainer;
use pocketmine\block\utils\AnimatedContainerTrait;
+use pocketmine\block\utils\AnyFacing;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
@@ -41,7 +43,7 @@ use pocketmine\world\sound\ShulkerBoxCloseSound;
use pocketmine\world\sound\ShulkerBoxOpenSound;
use pocketmine\world\sound\Sound;
-class ShulkerBox extends Opaque implements AnimatedContainer{
+class ShulkerBox extends Opaque implements AnimatedContainer, AnyFacing{
use AnimatedContainerTrait;
use AnyFacingTrait;
@@ -71,7 +73,7 @@ class ShulkerBox extends Opaque implements AnimatedContainer{
return 1;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
@@ -103,7 +105,7 @@ class ShulkerBox extends Opaque implements AnimatedContainer{
return $result;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
$shulker = $this->position->getWorld()->getTile($this->position);
@@ -122,7 +124,7 @@ class ShulkerBox extends Opaque implements AnimatedContainer{
return true;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
diff --git a/src/block/SimplePillar.php b/src/block/SimplePillar.php
index 98c89f89c..6a7af96ed 100644
--- a/src/block/SimplePillar.php
+++ b/src/block/SimplePillar.php
@@ -23,12 +23,13 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\PillarRotation;
use pocketmine\block\utils\PillarRotationTrait;
/**
* @internal This class provides a general base for pillar-like blocks. It **should not** be used for contract binding
* in APIs, because not all pillar-like blocks extend this class.
*/
-class SimplePillar extends Opaque{
+class SimplePillar extends Opaque implements PillarRotation{
use PillarRotationTrait;
}
diff --git a/src/block/Slab.php b/src/block/Slab.php
index 2bbb7528c..0ecee2571 100644
--- a/src/block/Slab.php
+++ b/src/block/Slab.php
@@ -63,7 +63,7 @@ class Slab extends Transparent{
return $this;
}
- public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
+ public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, Facing $face, bool $isClickedBlock) : bool{
if(parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock)){
return true;
}
@@ -79,7 +79,7 @@ class Slab extends Transparent{
return false;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockReplace instanceof Slab && $blockReplace->slabType !== SlabType::DOUBLE && $blockReplace->hasSameTypeId($this) && (
($blockReplace->slabType === SlabType::TOP && ($clickVector->y <= 0.5 || $face === Facing::UP)) ||
($blockReplace->slabType === SlabType::BOTTOM && ($clickVector->y >= 0.5 || $face === Facing::DOWN))
@@ -97,10 +97,10 @@ class Slab extends Transparent{
if($this->slabType === SlabType::DOUBLE){
return [AxisAlignedBB::one()];
}
- return [AxisAlignedBB::one()->trim($this->slabType === SlabType::TOP ? Facing::DOWN : Facing::UP, 0.5)];
+ return [AxisAlignedBB::one()->trimmedCopy($this->slabType === SlabType::TOP ? Facing::DOWN : Facing::UP, 0.5)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
if($this->slabType === SlabType::DOUBLE){
return SupportType::FULL;
}elseif(($facing === Facing::UP && $this->slabType === SlabType::TOP) || ($facing === Facing::DOWN && $this->slabType === SlabType::BOTTOM)){
diff --git a/src/block/SmallDripleaf.php b/src/block/SmallDripleaf.php
index d192e43db..abf428ce5 100644
--- a/src/block/SmallDripleaf.php
+++ b/src/block/SmallDripleaf.php
@@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -36,13 +38,13 @@ use pocketmine\world\BlockTransaction;
use pocketmine\world\Position;
use function mt_rand;
-class SmallDripleaf extends Transparent{
+class SmallDripleaf extends Transparent implements HorizontalFacing{
use HorizontalFacingTrait;
protected bool $top = false;
public function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->top);
}
@@ -74,13 +76,13 @@ class SmallDripleaf extends Transparent{
}
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$block = $blockReplace->getSide(Facing::UP);
if($block->getTypeId() !== BlockTypeIds::AIR || !$this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
return false;
}
if($player !== null){
- $this->facing = Facing::opposite($player->getHorizontalFacing());
+ $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
}
$tx->addBlock($block->position, VanillaBlocks::SMALL_DRIPLEAF()
@@ -90,7 +92,7 @@ class SmallDripleaf extends Transparent{
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{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
return true;
@@ -160,7 +162,7 @@ class SmallDripleaf extends Transparent{
return 100;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
diff --git a/src/block/SmithingTable.php b/src/block/SmithingTable.php
index b96a582d1..01fdbc189 100644
--- a/src/block/SmithingTable.php
+++ b/src/block/SmithingTable.php
@@ -25,12 +25,13 @@ namespace pocketmine\block;
use pocketmine\block\inventory\window\SmithingTableInventoryWindow;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
final class SmithingTable extends Opaque{
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){
$player->setCurrentWindow(new SmithingTableInventoryWindow($player, $this->position));
}
diff --git a/src/block/SnowLayer.php b/src/block/SnowLayer.php
index 8549f0b31..8669bdd65 100644
--- a/src/block/SnowLayer.php
+++ b/src/block/SnowLayer.php
@@ -67,10 +67,10 @@ class SnowLayer extends Flowable implements Fallable{
protected function recalculateCollisionBoxes() : array{
//TODO: this zero-height BB is intended to stay in lockstep with a MCPE bug
- return [AxisAlignedBB::one()->trim(Facing::UP, $this->layers >= 4 ? 0.5 : 1)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, $this->layers >= 4 ? 0.5 : 1)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
if(!$this->canBeReplaced()){
return SupportType::FULL;
}
@@ -81,7 +81,7 @@ class SnowLayer extends Flowable implements Fallable{
return $block->getAdjacentSupportType(Facing::DOWN) === SupportType::FULL;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockReplace instanceof SnowLayer){
if($blockReplace->layers >= self::MAX_LAYERS){
return false;
diff --git a/src/block/SoulSand.php b/src/block/SoulSand.php
index e1285d095..e1b30a90d 100644
--- a/src/block/SoulSand.php
+++ b/src/block/SoulSand.php
@@ -29,6 +29,6 @@ use pocketmine\math\Facing;
class SoulSand extends Opaque{
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 8)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 1 / 8)];
}
}
diff --git a/src/block/StainedGlass.php b/src/block/StainedGlass.php
index bc0d84877..baf4755bb 100644
--- a/src/block/StainedGlass.php
+++ b/src/block/StainedGlass.php
@@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
-final class StainedGlass extends Glass{
+final class StainedGlass extends Glass implements Colored{
use ColoredTrait;
}
diff --git a/src/block/StainedGlassPane.php b/src/block/StainedGlassPane.php
index 18ecfdee0..897c291c7 100644
--- a/src/block/StainedGlassPane.php
+++ b/src/block/StainedGlassPane.php
@@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
-final class StainedGlassPane extends GlassPane{
+final class StainedGlassPane extends GlassPane implements Colored{
use ColoredTrait;
}
diff --git a/src/block/StainedHardenedClay.php b/src/block/StainedHardenedClay.php
index 2c2c01ba3..765e97e4f 100644
--- a/src/block/StainedHardenedClay.php
+++ b/src/block/StainedHardenedClay.php
@@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
-final class StainedHardenedClay extends HardenedClay{
+final class StainedHardenedClay extends HardenedClay implements Colored{
use ColoredTrait;
}
diff --git a/src/block/StainedHardenedGlass.php b/src/block/StainedHardenedGlass.php
index cc609a49a..c3a794e4d 100644
--- a/src/block/StainedHardenedGlass.php
+++ b/src/block/StainedHardenedGlass.php
@@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
-final class StainedHardenedGlass extends HardenedGlass{
+final class StainedHardenedGlass extends HardenedGlass implements Colored{
use ColoredTrait;
}
diff --git a/src/block/StainedHardenedGlassPane.php b/src/block/StainedHardenedGlassPane.php
index 63dbe1f77..9631ff5a9 100644
--- a/src/block/StainedHardenedGlassPane.php
+++ b/src/block/StainedHardenedGlassPane.php
@@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
-final class StainedHardenedGlassPane extends HardenedGlassPane{
+final class StainedHardenedGlassPane extends HardenedGlassPane implements Colored{
use ColoredTrait;
}
diff --git a/src/block/Stair.php b/src/block/Stair.php
index d66a9ce5c..6e58dd985 100644
--- a/src/block/Stair.php
+++ b/src/block/Stair.php
@@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\StairShape;
use pocketmine\block\utils\SupportType;
@@ -35,14 +37,14 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-class Stair extends Transparent{
+class Stair extends Transparent implements HorizontalFacing{
use HorizontalFacingTrait;
protected bool $upsideDown = false;
protected StairShape $shape = StairShape::STRAIGHT;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->upsideDown);
}
@@ -51,7 +53,7 @@ class Stair extends Transparent{
$this->collisionBoxes = null;
- $clockwise = Facing::rotateY($this->facing, true);
+ $clockwise = HorizontalFacingOption::fromFacing(Facing::rotateY($this->facing->toFacing(), true));
if(($backFacing = $this->getPossibleCornerFacing(false)) !== null){
$this->shape = $backFacing === $clockwise ? StairShape::OUTER_RIGHT : StairShape::OUTER_LEFT;
}elseif(($frontFacing = $this->getPossibleCornerFacing(true)) !== null){
@@ -82,21 +84,22 @@ class Stair extends Transparent{
protected function recalculateCollisionBoxes() : array{
$topStepFace = $this->upsideDown ? Facing::DOWN : Facing::UP;
$bbs = [
- AxisAlignedBB::one()->trim($topStepFace, 0.5)
+ AxisAlignedBB::one()->trimmedCopy($topStepFace, 0.5)
];
+ $realFacing = $this->facing->toFacing();
$topStep = AxisAlignedBB::one()
- ->trim(Facing::opposite($topStepFace), 0.5)
- ->trim(Facing::opposite($this->facing), 0.5);
+ ->trimmedCopy(Facing::opposite($topStepFace), 0.5)
+ ->trimmedCopy(Facing::opposite($realFacing), 0.5);
if($this->shape === StairShape::OUTER_LEFT || $this->shape === StairShape::OUTER_RIGHT){
- $topStep->trim(Facing::rotateY($this->facing, $this->shape === StairShape::OUTER_LEFT), 0.5);
+ $topStep = $topStep->trimmedCopy(Facing::rotateY($realFacing, $this->shape === StairShape::OUTER_LEFT), 0.5);
}elseif($this->shape === StairShape::INNER_LEFT || $this->shape === StairShape::INNER_RIGHT){
//add an extra cube
$bbs[] = AxisAlignedBB::one()
- ->trim(Facing::opposite($topStepFace), 0.5)
- ->trim($this->facing, 0.5) //avoid overlapping with main step
- ->trim(Facing::rotateY($this->facing, $this->shape === StairShape::INNER_LEFT), 0.5);
+ ->trimmedCopy(Facing::opposite($topStepFace), 0.5)
+ ->trimmedCopy($realFacing, 0.5) //avoid overlapping with main step
+ ->trimmedCopy(Facing::rotateY($realFacing, $this->shape === StairShape::INNER_LEFT), 0.5);
}
$bbs[] = $topStep;
@@ -104,31 +107,33 @@ class Stair extends Transparent{
return $bbs;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
+ $realFacing = $this->facing->toFacing();
if(
$facing === Facing::UP && $this->upsideDown ||
$facing === Facing::DOWN && !$this->upsideDown ||
- ($facing === $this->facing && $this->shape !== StairShape::OUTER_LEFT && $this->shape !== StairShape::OUTER_RIGHT) ||
- ($facing === Facing::rotate($this->facing, Axis::Y, false) && $this->shape === StairShape::INNER_LEFT) ||
- ($facing === Facing::rotate($this->facing, Axis::Y, true) && $this->shape === StairShape::INNER_RIGHT)
+ ($facing === $realFacing && $this->shape !== StairShape::OUTER_LEFT && $this->shape !== StairShape::OUTER_RIGHT) ||
+ ($facing === Facing::rotate($realFacing, Axis::Y, false) && $this->shape === StairShape::INNER_LEFT) ||
+ ($facing === Facing::rotate($realFacing, Axis::Y, true) && $this->shape === StairShape::INNER_RIGHT)
){
return SupportType::FULL;
}
return SupportType::NONE;
}
- private function getPossibleCornerFacing(bool $oppositeFacing) : ?int{
- $side = $this->getSide($oppositeFacing ? Facing::opposite($this->facing) : $this->facing);
+ private function getPossibleCornerFacing(bool $oppositeFacing) : ?HorizontalFacingOption{
+ $realFacing = $this->facing->toFacing();
+ $side = $this->getSide($oppositeFacing ? Facing::opposite($realFacing) : $realFacing);
return (
$side instanceof Stair &&
$side->upsideDown === $this->upsideDown &&
- Facing::axis($side->facing) !== Facing::axis($this->facing) //perpendicular
+ Facing::axis($side->facing->toFacing()) !== Facing::axis($realFacing) //perpendicular
) ? $side->facing : null;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
- $this->facing = $player->getHorizontalFacing();
+ $this->facing = HorizontalFacingOption::fromFacing($player->getHorizontalFacing());
}
$this->upsideDown = (($clickVector->y > 0.5 && $face !== Facing::UP) || $face === Facing::DOWN);
diff --git a/src/block/Stem.php b/src/block/Stem.php
index 2ac95aa3f..8dbe915f1 100644
--- a/src/block/Stem.php
+++ b/src/block/Stem.php
@@ -25,24 +25,25 @@ namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\CropGrowthHelper;
+use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
+use pocketmine\item\VanillaItems;
use pocketmine\math\Facing;
use function array_rand;
-use function mt_rand;
abstract class Stem extends Crops{
- protected int $facing = Facing::UP;
+ protected Facing $facing = Facing::UP;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
parent::describeBlockOnlyState($w);
$w->facingExcept($this->facing, Facing::DOWN);
}
- public function getFacing() : int{ return $this->facing; }
+ public function getFacing() : Facing{ return $this->facing; }
/** @return $this */
- public function setFacing(int $facing) : self{
+ public function setFacing(Facing $facing) : self{
if($facing === Facing::DOWN){
throw new \InvalidArgumentException("DOWN is not a valid facing for this block");
}
@@ -90,8 +91,10 @@ abstract class Stem extends Crops{
}
public function getDropsForCompatibleTool(Item $item) : array{
+ //TODO: bit annoying we have to pass an Item instance here
+ //this should not be affected by Fortune, but still follows a binomial distribution
return [
- $this->asItem()->setCount(mt_rand(0, 2))
+ $this->asItem()->setCount(FortuneDropHelper::binomial(VanillaItems::AIR(), 0, chance: ($this->age + 1) / 15))
];
}
}
diff --git a/src/block/Stonecutter.php b/src/block/Stonecutter.php
index 3c22e74a8..f254b4950 100644
--- a/src/block/Stonecutter.php
+++ b/src/block/Stonecutter.php
@@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\inventory\window\StonecutterInventoryWindow;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
+use pocketmine\block\utils\HorizontalFacing;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
@@ -32,10 +33,10 @@ use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
-class Stonecutter extends Transparent{
+class Stonecutter extends Transparent implements HorizontalFacing{
use FacesOppositePlacingPlayerTrait;
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){
$player->setCurrentWindow(new StonecutterInventoryWindow($player, $this->position));
}
@@ -43,10 +44,10 @@ class Stonecutter extends Transparent{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim(Facing::UP, 7 / 16)];
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::UP, 7 / 16)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
}
diff --git a/src/block/StraightOnlyRail.php b/src/block/StraightOnlyRail.php
index 054983dbc..5a09474a5 100644
--- a/src/block/StraightOnlyRail.php
+++ b/src/block/StraightOnlyRail.php
@@ -24,20 +24,18 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\RailConnectionInfo;
-use pocketmine\data\bedrock\block\BlockLegacyMetadata;
+use pocketmine\block\utils\StraightOnlyRailShape;
use pocketmine\data\runtime\RuntimeDataDescriber;
-use function array_keys;
-use function implode;
/**
* Simple non-curvable rail.
*/
class StraightOnlyRail extends BaseRail{
- private int $railShape = BlockLegacyMetadata::RAIL_STRAIGHT_NORTH_SOUTH;
+ private StraightOnlyRailShape $railShape = StraightOnlyRailShape::FLAT_AXIS_Z;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->straightOnlyRailShape($this->railShape);
+ $w->enum($this->railShape);
}
protected function setShapeFromConnections(array $connections) : void{
@@ -45,20 +43,17 @@ class StraightOnlyRail extends BaseRail{
if($railShape === null){
throw new \InvalidArgumentException("No rail shape matches these connections");
}
- $this->railShape = $railShape;
+ $this->railShape = StraightOnlyRailShape::from($railShape);
}
protected function getCurrentShapeConnections() : array{
- return RailConnectionInfo::CONNECTIONS[$this->railShape];
+ return RailConnectionInfo::CONNECTIONS[$this->railShape->value];
}
- public function getShape() : int{ return $this->railShape; }
+ public function getShape() : StraightOnlyRailShape{ return $this->railShape; }
/** @return $this */
- public function setShape(int $shape) : self{
- if(!isset(RailConnectionInfo::CONNECTIONS[$shape])){
- throw new \InvalidArgumentException("Invalid rail shape, must be one of " . implode(", ", array_keys(RailConnectionInfo::CONNECTIONS)));
- }
+ public function setShape(StraightOnlyRailShape $shape) : self{
$this->railShape = $shape;
return $this;
diff --git a/src/block/Sugarcane.php b/src/block/Sugarcane.php
index 2da2dc9b9..0f8d7e13c 100644
--- a/src/block/Sugarcane.php
+++ b/src/block/Sugarcane.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\StaticSupportTrait;
@@ -34,7 +35,7 @@ use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\Position;
-class Sugarcane extends Flowable{
+class Sugarcane extends Flowable implements Ageable{
use AgeableTrait;
use StaticSupportTrait {
onNearbyBlockChange as onSupportBlockChange;
@@ -74,7 +75,7 @@ class Sugarcane extends Flowable{
return $grew;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer){
if($this->grow($this->seekToBottom(), $player)){
$item->pop();
@@ -115,7 +116,7 @@ class Sugarcane extends Flowable{
}
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $blockReplace->getSide(Facing::DOWN);
if($down->hasSameTypeId($this)){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
diff --git a/src/block/SweetBerryBush.php b/src/block/SweetBerryBush.php
index 5fd7fcaa1..1b7ce5bad 100644
--- a/src/block/SweetBerryBush.php
+++ b/src/block/SweetBerryBush.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Ageable;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\FortuneDropHelper;
@@ -39,7 +40,7 @@ use pocketmine\player\Player;
use pocketmine\world\sound\SweetBerriesPickSound;
use function mt_rand;
-class SweetBerryBush extends Flowable{
+class SweetBerryBush extends Flowable implements Ageable{
use AgeableTrait;
use StaticSupportTrait;
@@ -64,7 +65,7 @@ class SweetBerryBush extends Flowable{
($supportBlock->hasTypeTag(BlockTypeTags::DIRT) || $supportBlock->hasTypeTag(BlockTypeTags::MUD));
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$world = $this->position->getWorld();
if($this->age < self::STAGE_MATURE && $item instanceof Fertilizer){
$block = clone $this;
diff --git a/src/block/TNT.php b/src/block/TNT.php
index a0256bb67..20543dcbd 100644
--- a/src/block/TNT.php
+++ b/src/block/TNT.php
@@ -32,6 +32,7 @@ use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\FlintSteel;
use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds;
+use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
@@ -77,7 +78,7 @@ class TNT extends Opaque{
return parent::onBreak($item, $player, $returnedItems);
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item->getTypeId() === ItemTypeIds::FIRE_CHARGE){
$item->pop();
$this->ignite();
diff --git a/src/block/Thin.php b/src/block/Thin.php
index 82010697a..585f70a80 100644
--- a/src/block/Thin.php
+++ b/src/block/Thin.php
@@ -44,9 +44,9 @@ class Thin extends Transparent{
foreach(Facing::HORIZONTAL as $facing){
$side = $this->getSide($facing);
if($side instanceof Thin || $side instanceof Wall || $side->getSupportType(Facing::opposite($facing)) === SupportType::FULL){
- $this->connections[$facing] = true;
+ $this->connections[$facing->value] = true;
}else{
- unset($this->connections[$facing]);
+ unset($this->connections[$facing->value]);
}
}
@@ -58,24 +58,24 @@ class Thin extends Transparent{
$bbs = [];
- if(isset($this->connections[Facing::WEST]) || isset($this->connections[Facing::EAST])){
- $bb = AxisAlignedBB::one()->squash(Axis::Z, $inset);
+ if(isset($this->connections[Facing::WEST->value]) || isset($this->connections[Facing::EAST->value])){
+ $bb = AxisAlignedBB::one()->squashedCopy(Axis::Z, $inset);
- if(!isset($this->connections[Facing::WEST])){
- $bb->trim(Facing::WEST, $inset);
- }elseif(!isset($this->connections[Facing::EAST])){
- $bb->trim(Facing::EAST, $inset);
+ if(!isset($this->connections[Facing::WEST->value])){
+ $bb = $bb->trimmedCopy(Facing::WEST, $inset);
+ }elseif(!isset($this->connections[Facing::EAST->value])){
+ $bb = $bb->trimmedCopy(Facing::EAST, $inset);
}
$bbs[] = $bb;
}
- if(isset($this->connections[Facing::NORTH]) || isset($this->connections[Facing::SOUTH])){
- $bb = AxisAlignedBB::one()->squash(Axis::X, $inset);
+ if(isset($this->connections[Facing::NORTH->value]) || isset($this->connections[Facing::SOUTH->value])){
+ $bb = AxisAlignedBB::one()->squashedCopy(Axis::X, $inset);
- if(!isset($this->connections[Facing::NORTH])){
- $bb->trim(Facing::NORTH, $inset);
- }elseif(!isset($this->connections[Facing::SOUTH])){
- $bb->trim(Facing::SOUTH, $inset);
+ if(!isset($this->connections[Facing::NORTH->value])){
+ $bb = $bb->trimmedCopy(Facing::NORTH, $inset);
+ }elseif(!isset($this->connections[Facing::SOUTH->value])){
+ $bb = $bb->trimmedCopy(Facing::SOUTH, $inset);
}
$bbs[] = $bb;
}
@@ -83,14 +83,14 @@ class Thin extends Transparent{
if(count($bbs) === 0){
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
return [
- AxisAlignedBB::one()->contract($inset, 0, $inset)
+ AxisAlignedBB::one()->contractedCopy($inset, 0, $inset)
];
}
return $bbs;
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
}
diff --git a/src/block/Torch.php b/src/block/Torch.php
index aee4da32a..3d108a816 100644
--- a/src/block/Torch.php
+++ b/src/block/Torch.php
@@ -33,16 +33,16 @@ use pocketmine\world\BlockTransaction;
class Torch extends Flowable{
- protected int $facing = Facing::UP;
+ protected Facing $facing = Facing::UP;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->facingExcept($this->facing, Facing::DOWN);
}
- public function getFacing() : int{ return $this->facing; }
+ public function getFacing() : Facing{ return $this->facing; }
/** @return $this */
- public function setFacing(int $facing) : self{
+ public function setFacing(Facing $facing) : self{
if($facing === Facing::DOWN){
throw new \InvalidArgumentException("Torch may not face DOWN");
}
@@ -60,7 +60,7 @@ class Torch extends Flowable{
}
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face !== Facing::DOWN && $this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
@@ -81,7 +81,7 @@ class Torch extends Flowable{
return false;
}
- private function canBeSupportedAt(Block $block, int $face) : bool{
+ private function canBeSupportedAt(Block $block, Facing $face) : bool{
return $face === Facing::DOWN ?
$block->getAdjacentSupportType($face)->hasCenterSupport() :
$block->getAdjacentSupportType($face) === SupportType::FULL;
diff --git a/src/block/TorchflowerCrop.php b/src/block/TorchflowerCrop.php
index 033b08552..a5dc2dcbb 100644
--- a/src/block/TorchflowerCrop.php
+++ b/src/block/TorchflowerCrop.php
@@ -62,7 +62,7 @@ final class TorchflowerCrop extends Flowable{
}
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer){
if(BlockEventHelper::grow($this, $this->getNextState(), $player)){
$item->pop();
diff --git a/src/block/Trapdoor.php b/src/block/Trapdoor.php
index a903e1b5e..81c165840 100644
--- a/src/block/Trapdoor.php
+++ b/src/block/Trapdoor.php
@@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
@@ -34,14 +36,14 @@ use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\DoorSound;
-class Trapdoor extends Transparent{
+class Trapdoor extends Transparent implements HorizontalFacing{
use HorizontalFacingTrait;
protected bool $open = false;
protected bool $top = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->top);
$w->bool($this->open);
}
@@ -63,16 +65,16 @@ class Trapdoor extends Transparent{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->trim($this->open ? $this->facing : ($this->top ? Facing::DOWN : Facing::UP), 13 / 16)];
+ return [AxisAlignedBB::one()->trimmedCopy($this->open ? $this->facing->toFacing() : ($this->top ? Facing::DOWN : Facing::UP), 13 / 16)];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return SupportType::NONE;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
- $this->facing = Facing::opposite($player->getHorizontalFacing());
+ $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
}
if(($clickVector->y > 0.5 && $face !== Facing::UP) || $face === Facing::DOWN){
$this->top = true;
@@ -81,7 +83,7 @@ class Trapdoor extends Transparent{
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{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$this->open = !$this->open;
$world = $this->position->getWorld();
$world->setBlock($this->position, $this);
diff --git a/src/block/TripwireHook.php b/src/block/TripwireHook.php
index 325819825..3f82985b0 100644
--- a/src/block/TripwireHook.php
+++ b/src/block/TripwireHook.php
@@ -23,23 +23,24 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
-use pocketmine\math\Axis;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-class TripwireHook extends Flowable{
+class TripwireHook extends Flowable implements HorizontalFacing{
use HorizontalFacingTrait;
protected bool $connected = false;
protected bool $powered = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
$w->bool($this->connected);
$w->bool($this->powered);
}
@@ -60,10 +61,10 @@ class TripwireHook extends Flowable{
return $this;
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
- if(Facing::axis($face) !== Axis::Y){
- //TODO: check face is valid
- $this->facing = $face;
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ $hzFacing = HorizontalFacingOption::tryFromFacing($face);
+ if($hzFacing !== null){
+ $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
return false;
diff --git a/src/block/VanillaBlocks.php b/src/block/VanillaBlocks.php
index f4c318f32..569efe0d3 100644
--- a/src/block/VanillaBlocks.php
+++ b/src/block/VanillaBlocks.php
@@ -45,6 +45,7 @@ use pocketmine\block\tile\EnchantTable as TileEnchantingTable;
use pocketmine\block\tile\EnderChest as TileEnderChest;
use pocketmine\block\tile\FlowerPot as TileFlowerPot;
use pocketmine\block\tile\GlowingItemFrame as TileGlowingItemFrame;
+use pocketmine\block\tile\HangingSign as TileHangingSign;
use pocketmine\block\tile\Hopper as TileHopper;
use pocketmine\block\tile\ItemFrame as TileItemFrame;
use pocketmine\block\tile\Jukebox as TileJukebox;
@@ -80,6 +81,8 @@ use function strtolower;
* @generate-registry-docblock
*
* @method static WoodenButton ACACIA_BUTTON()
+ * @method static CeilingCenterHangingSign ACACIA_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign ACACIA_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor ACACIA_DOOR()
* @method static WoodenFence ACACIA_FENCE()
* @method static FenceGate ACACIA_FENCE_GATE()
@@ -92,6 +95,7 @@ use function strtolower;
* @method static WoodenSlab ACACIA_SLAB()
* @method static WoodenStairs ACACIA_STAIRS()
* @method static WoodenTrapdoor ACACIA_TRAPDOOR()
+ * @method static WallHangingSign ACACIA_WALL_HANGING_SIGN()
* @method static WallSign ACACIA_WALL_SIGN()
* @method static Wood ACACIA_WOOD()
* @method static ActivatorRail ACTIVATOR_RAIL()
@@ -122,6 +126,8 @@ use function strtolower;
* @method static BigDripleafHead BIG_DRIPLEAF_HEAD()
* @method static BigDripleafStem BIG_DRIPLEAF_STEM()
* @method static WoodenButton BIRCH_BUTTON()
+ * @method static CeilingCenterHangingSign BIRCH_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign BIRCH_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor BIRCH_DOOR()
* @method static WoodenFence BIRCH_FENCE()
* @method static FenceGate BIRCH_FENCE_GATE()
@@ -134,6 +140,7 @@ use function strtolower;
* @method static WoodenSlab BIRCH_SLAB()
* @method static WoodenStairs BIRCH_STAIRS()
* @method static WoodenTrapdoor BIRCH_TRAPDOOR()
+ * @method static WallHangingSign BIRCH_WALL_HANGING_SIGN()
* @method static WallSign BIRCH_WALL_SIGN()
* @method static Wood BIRCH_WOOD()
* @method static Opaque BLACKSTONE()
@@ -170,6 +177,8 @@ use function strtolower;
* @method static Chain CHAIN()
* @method static ChemicalHeat CHEMICAL_HEAT()
* @method static WoodenButton CHERRY_BUTTON()
+ * @method static CeilingCenterHangingSign CHERRY_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign CHERRY_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor CHERRY_DOOR()
* @method static WoodenFence CHERRY_FENCE()
* @method static FenceGate CHERRY_FENCE_GATE()
@@ -181,6 +190,7 @@ use function strtolower;
* @method static WoodenSlab CHERRY_SLAB()
* @method static WoodenStairs CHERRY_STAIRS()
* @method static WoodenTrapdoor CHERRY_TRAPDOOR()
+ * @method static WallHangingSign CHERRY_WALL_HANGING_SIGN()
* @method static WallSign CHERRY_WALL_SIGN()
* @method static Wood CHERRY_WOOD()
* @method static Chest CHEST()
@@ -231,6 +241,8 @@ use function strtolower;
* @method static Opaque CRACKED_STONE_BRICKS()
* @method static CraftingTable CRAFTING_TABLE()
* @method static WoodenButton CRIMSON_BUTTON()
+ * @method static CeilingCenterHangingSign CRIMSON_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign CRIMSON_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor CRIMSON_DOOR()
* @method static WoodenFence CRIMSON_FENCE()
* @method static FenceGate CRIMSON_FENCE_GATE()
@@ -243,6 +255,7 @@ use function strtolower;
* @method static WoodenStairs CRIMSON_STAIRS()
* @method static Wood CRIMSON_STEM()
* @method static WoodenTrapdoor CRIMSON_TRAPDOOR()
+ * @method static WallHangingSign CRIMSON_WALL_HANGING_SIGN()
* @method static WallSign CRIMSON_WALL_SIGN()
* @method static Opaque CRYING_OBSIDIAN()
* @method static Copper CUT_COPPER()
@@ -254,6 +267,8 @@ use function strtolower;
* @method static Slab CUT_SANDSTONE_SLAB()
* @method static Flower DANDELION()
* @method static WoodenButton DARK_OAK_BUTTON()
+ * @method static CeilingCenterHangingSign DARK_OAK_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign DARK_OAK_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor DARK_OAK_DOOR()
* @method static WoodenFence DARK_OAK_FENCE()
* @method static FenceGate DARK_OAK_FENCE_GATE()
@@ -266,6 +281,7 @@ use function strtolower;
* @method static WoodenSlab DARK_OAK_SLAB()
* @method static WoodenStairs DARK_OAK_STAIRS()
* @method static WoodenTrapdoor DARK_OAK_TRAPDOOR()
+ * @method static WallHangingSign DARK_OAK_WALL_HANGING_SIGN()
* @method static WallSign DARK_OAK_WALL_SIGN()
* @method static Wood DARK_OAK_WOOD()
* @method static Opaque DARK_PRISMARINE()
@@ -488,6 +504,8 @@ use function strtolower;
* @method static ItemFrame ITEM_FRAME()
* @method static Jukebox JUKEBOX()
* @method static WoodenButton JUNGLE_BUTTON()
+ * @method static CeilingCenterHangingSign JUNGLE_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign JUNGLE_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor JUNGLE_DOOR()
* @method static WoodenFence JUNGLE_FENCE()
* @method static FenceGate JUNGLE_FENCE_GATE()
@@ -500,6 +518,7 @@ use function strtolower;
* @method static WoodenSlab JUNGLE_SLAB()
* @method static WoodenStairs JUNGLE_STAIRS()
* @method static WoodenTrapdoor JUNGLE_TRAPDOOR()
+ * @method static WallHangingSign JUNGLE_WALL_HANGING_SIGN()
* @method static WallSign JUNGLE_WALL_SIGN()
* @method static Wood JUNGLE_WOOD()
* @method static ChemistryTable LAB_TABLE()
@@ -522,6 +541,8 @@ use function strtolower;
* @method static Loom LOOM()
* @method static Magma MAGMA()
* @method static WoodenButton MANGROVE_BUTTON()
+ * @method static CeilingCenterHangingSign MANGROVE_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign MANGROVE_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor MANGROVE_DOOR()
* @method static WoodenFence MANGROVE_FENCE()
* @method static FenceGate MANGROVE_FENCE_GATE()
@@ -534,6 +555,7 @@ use function strtolower;
* @method static WoodenSlab MANGROVE_SLAB()
* @method static WoodenStairs MANGROVE_STAIRS()
* @method static WoodenTrapdoor MANGROVE_TRAPDOOR()
+ * @method static WallHangingSign MANGROVE_WALL_HANGING_SIGN()
* @method static WallSign MANGROVE_WALL_SIGN()
* @method static Wood MANGROVE_WOOD()
* @method static ChemistryTable MATERIAL_REDUCER()
@@ -572,6 +594,8 @@ use function strtolower;
* @method static Opaque NETHER_WART_BLOCK()
* @method static Note NOTE_BLOCK()
* @method static WoodenButton OAK_BUTTON()
+ * @method static CeilingCenterHangingSign OAK_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign OAK_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor OAK_DOOR()
* @method static WoodenFence OAK_FENCE()
* @method static FenceGate OAK_FENCE_GATE()
@@ -584,14 +608,19 @@ use function strtolower;
* @method static WoodenSlab OAK_SLAB()
* @method static WoodenStairs OAK_STAIRS()
* @method static WoodenTrapdoor OAK_TRAPDOOR()
+ * @method static WallHangingSign OAK_WALL_HANGING_SIGN()
* @method static WallSign OAK_WALL_SIGN()
* @method static Wood OAK_WOOD()
* @method static Opaque OBSIDIAN()
+ * @method static OminousFloorBanner OMINOUS_BANNER()
+ * @method static OminousWallBanner OMINOUS_WALL_BANNER()
* @method static Flower ORANGE_TULIP()
* @method static Flower OXEYE_DAISY()
* @method static PackedIce PACKED_ICE()
* @method static Opaque PACKED_MUD()
* @method static WoodenButton PALE_OAK_BUTTON()
+ * @method static CeilingCenterHangingSign PALE_OAK_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign PALE_OAK_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor PALE_OAK_DOOR()
* @method static WoodenFence PALE_OAK_FENCE()
* @method static FenceGate PALE_OAK_FENCE_GATE()
@@ -603,6 +632,7 @@ use function strtolower;
* @method static WoodenSlab PALE_OAK_SLAB()
* @method static WoodenStairs PALE_OAK_STAIRS()
* @method static WoodenTrapdoor PALE_OAK_TRAPDOOR()
+ * @method static WallHangingSign PALE_OAK_WALL_HANGING_SIGN()
* @method static WallSign PALE_OAK_WALL_SIGN()
* @method static Wood PALE_OAK_WOOD()
* @method static DoublePlant PEONY()
@@ -694,6 +724,7 @@ use function strtolower;
* @method static Stair RESIN_BRICK_STAIRS()
* @method static Wall RESIN_BRICK_WALL()
* @method static ResinClump RESIN_CLUMP()
+ * @method static RespawnAnchor RESPAWN_ANCHOR()
* @method static DoublePlant ROSE_BUSH()
* @method static Sand SAND()
* @method static Opaque SANDSTONE()
@@ -732,6 +763,8 @@ use function strtolower;
* @method static Sponge SPONGE()
* @method static SporeBlossom SPORE_BLOSSOM()
* @method static WoodenButton SPRUCE_BUTTON()
+ * @method static CeilingCenterHangingSign SPRUCE_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign SPRUCE_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor SPRUCE_DOOR()
* @method static WoodenFence SPRUCE_FENCE()
* @method static FenceGate SPRUCE_FENCE_GATE()
@@ -744,6 +777,7 @@ use function strtolower;
* @method static WoodenSlab SPRUCE_SLAB()
* @method static WoodenStairs SPRUCE_STAIRS()
* @method static WoodenTrapdoor SPRUCE_TRAPDOOR()
+ * @method static WallHangingSign SPRUCE_WALL_HANGING_SIGN()
* @method static WallSign SPRUCE_WALL_SIGN()
* @method static Wood SPRUCE_WOOD()
* @method static StainedHardenedClay STAINED_CLAY()
@@ -787,6 +821,8 @@ use function strtolower;
* @method static WallBanner WALL_BANNER()
* @method static WallCoralFan WALL_CORAL_FAN()
* @method static WoodenButton WARPED_BUTTON()
+ * @method static CeilingCenterHangingSign WARPED_CEILING_CENTER_HANGING_SIGN()
+ * @method static CeilingEdgesHangingSign WARPED_CEILING_EDGES_HANGING_SIGN()
* @method static WoodenDoor WARPED_DOOR()
* @method static WoodenFence WARPED_FENCE()
* @method static FenceGate WARPED_FENCE_GATE()
@@ -799,6 +835,7 @@ use function strtolower;
* @method static WoodenStairs WARPED_STAIRS()
* @method static Wood WARPED_STEM()
* @method static WoodenTrapdoor WARPED_TRAPDOOR()
+ * @method static WallHangingSign WARPED_WALL_HANGING_SIGN()
* @method static WallSign WARPED_WALL_SIGN()
* @method static Opaque WARPED_WART_BLOCK()
* @method static Water WATER()
@@ -859,7 +896,7 @@ final class VanillaBlocks{
$railBreakInfo = new Info(new BreakInfo(0.7));
self::register("activator_rail", fn(BID $id) => new ActivatorRail($id, "Activator Rail", $railBreakInfo));
self::register("anvil", fn(BID $id) => new Anvil($id, "Anvil", new Info(BreakInfo::pickaxe(5.0, ToolTier::WOOD, 6000.0))));
- self::register("bamboo", fn(BID $id) => new Bamboo($id, "Bamboo", new Info(new class(2.0 /* 1.0 in PC */, ToolType::AXE) extends BreakInfo{
+ self::register("bamboo", fn(BID $id) => new Bamboo($id, "Bamboo", new Info(new class(1.0, ToolType::AXE) extends BreakInfo{
public function getBreakTime(Item $item) : float{
if($item->getBlockToolType() === ToolType::SWORD){
return 0.0;
@@ -867,16 +904,18 @@ final class VanillaBlocks{
return parent::getBreakTime($item);
}
}, [Tags::POTTABLE_PLANTS])));
- self::register("bamboo_sapling", fn(BID $id) => new BambooSapling($id, "Bamboo Sapling", new Info(BreakInfo::instant())));
+ self::register("bamboo_sapling", fn(BID $id) => new BambooSapling($id, "Bamboo Sapling", new Info(new BreakInfo(1.0))));
$bannerBreakInfo = new Info(BreakInfo::axe(1.0));
self::register("banner", fn(BID $id) => new FloorBanner($id, "Banner", $bannerBreakInfo), TileBanner::class);
self::register("wall_banner", fn(BID $id) => new WallBanner($id, "Wall Banner", $bannerBreakInfo), TileBanner::class);
+ self::register("ominous_banner", fn(BID $id) => new OminousFloorBanner($id, "Ominous Banner", $bannerBreakInfo), TileBanner::class);
+ self::register("ominous_wall_banner", fn(BID $id) => new OminousWallBanner($id, "Ominous Wall Banner", $bannerBreakInfo), TileBanner::class);
self::register("barrel", fn(BID $id) => new Barrel($id, "Barrel", new Info(BreakInfo::axe(2.5))), TileBarrel::class);
self::register("barrier", fn(BID $id) => new Transparent($id, "Barrier", new Info(BreakInfo::indestructible())));
self::register("beacon", fn(BID $id) => new Beacon($id, "Beacon", new Info(new BreakInfo(3.0))), TileBeacon::class);
self::register("bed", fn(BID $id) => new Bed($id, "Bed Block", new Info(new BreakInfo(0.2))), TileBed::class);
- self::register("bedrock", fn(BID $id) => new Bedrock($id, "Bedrock", new Info(BreakInfo::indestructible())));
+ self::register("bedrock", fn(BID $id) => new Bedrock($id, "Bedrock", new Info(BreakInfo::indestructible(18000000.0))));
self::register("beetroots", fn(BID $id) => new Beetroot($id, "Beetroot Block", new Info(BreakInfo::instant())));
self::register("bell", fn(BID $id) => new Bell($id, "Bell", new Info(BreakInfo::pickaxe(5.0))), TileBell::class);
@@ -913,7 +952,7 @@ final class VanillaBlocks{
self::register("cobweb", fn(BID $id) => new Cobweb($id, "Cobweb", new Info(new BreakInfo(4.0, ToolType::SWORD | ToolType::SHEARS, 1))));
self::register("cocoa_pod", fn(BID $id) => new CocoaBlock($id, "Cocoa Block", new Info(BreakInfo::axe(0.2, null, 15.0))));
- self::register("coral_block", fn(BID $id) => new CoralBlock($id, "Coral Block", new Info(BreakInfo::pickaxe(7.0, ToolTier::WOOD))));
+ self::register("coral_block", fn(BID $id) => new CoralBlock($id, "Coral Block", new Info(BreakInfo::pickaxe(1.5, ToolTier::WOOD, 30.0))));
self::register("daylight_sensor", fn(BID $id) => new DaylightSensor($id, "Daylight Sensor", new Info(BreakInfo::axe(0.2))), TileDaylightSensor::class);
self::register("dead_bush", fn(BID $id) => new DeadBush($id, "Dead Bush", new Info(BreakInfo::instant(ToolType::SHEARS, 1), [Tags::POTTABLE_PLANTS])));
self::register("detector_rail", fn(BID $id) => new DetectorRail($id, "Detector Rail", $railBreakInfo));
@@ -930,15 +969,15 @@ final class VanillaBlocks{
self::register("pitcher_plant", fn(BID $id) => new DoublePlant($id, "Pitcher Plant", new Info(BreakInfo::instant())));
self::register("pitcher_crop", fn(BID $id) => new PitcherCrop($id, "Pitcher Crop", new Info(BreakInfo::instant())));
self::register("double_pitcher_crop", fn(BID $id) => new DoublePitcherCrop($id, "Double Pitcher Crop", new Info(BreakInfo::instant())));
- self::register("dragon_egg", fn(BID $id) => new DragonEgg($id, "Dragon Egg", new Info(BreakInfo::pickaxe(3.0, ToolTier::WOOD))));
+ self::register("dragon_egg", fn(BID $id) => new DragonEgg($id, "Dragon Egg", new Info(BreakInfo::pickaxe(3.0, ToolTier::WOOD, blastResistance: 45.0))));
self::register("dried_kelp", fn(BID $id) => new DriedKelp($id, "Dried Kelp Block", new Info(new BreakInfo(0.5, ToolType::NONE, 0, 12.5))));
self::register("emerald", fn(BID $id) => new Opaque($id, "Emerald Block", new Info(BreakInfo::pickaxe(5.0, ToolTier::IRON, 30.0))));
self::register("enchanting_table", fn(BID $id) => new EnchantingTable($id, "Enchanting Table", new Info(BreakInfo::pickaxe(5.0, ToolTier::WOOD, 6000.0))), TileEnchantingTable::class);
- self::register("end_portal_frame", fn(BID $id) => new EndPortalFrame($id, "End Portal Frame", new Info(BreakInfo::indestructible())));
+ self::register("end_portal_frame", fn(BID $id) => new EndPortalFrame($id, "End Portal Frame", new Info(BreakInfo::indestructible(18000000.0))));
self::register("end_rod", fn(BID $id) => new EndRod($id, "End Rod", new Info(BreakInfo::instant())));
self::register("end_stone", fn(BID $id) => new Opaque($id, "End Stone", new Info(BreakInfo::pickaxe(3.0, ToolTier::WOOD, 45.0))));
- $endBrickBreakInfo = new Info(BreakInfo::pickaxe(0.8, ToolTier::WOOD, 4.0));
+ $endBrickBreakInfo = new Info(BreakInfo::pickaxe(3.0, ToolTier::WOOD, 45.0));
self::register("end_stone_bricks", fn(BID $id) => new Opaque($id, "End Stone Bricks", $endBrickBreakInfo));
self::register("end_stone_brick_stairs", fn(BID $id) => new Stair($id, "End Stone Brick Stairs", $endBrickBreakInfo));
@@ -962,7 +1001,7 @@ final class VanillaBlocks{
self::register("torchflower", fn(BID $id) => new Flower($id, "Torchflower", $flowerTypeInfo));
self::register("torchflower_crop", fn(BID $id) => new TorchflowerCrop($id, "Torchflower Crop", new Info(BreakInfo::instant())));
self::register("flower_pot", fn(BID $id) => new FlowerPot($id, "Flower Pot", new Info(BreakInfo::instant())), TileFlowerPot::class);
- self::register("frosted_ice", fn(BID $id) => new FrostedIce($id, "Frosted Ice", new Info(BreakInfo::pickaxe(2.5))));
+ self::register("frosted_ice", fn(BID $id) => new FrostedIce($id, "Frosted Ice", new Info(BreakInfo::pickaxe(0.5))));
self::register("furnace", fn(BID $id) => new Furnace($id, "Furnace", new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD)), FurnaceType::FURNACE), TileNormalFurnace::class);
self::register("blast_furnace", fn(BID $id) => new Furnace($id, "Blast Furnace", new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD)), FurnaceType::BLAST_FURNACE), TileBlastFurnace::class);
self::register("smoker", fn(BID $id) => new Furnace($id, "Smoker", new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD)), FurnaceType::SMOKER), TileSmoker::class);
@@ -970,30 +1009,28 @@ final class VanillaBlocks{
$glassBreakInfo = new Info(new BreakInfo(0.3));
self::register("glass", fn(BID $id) => new Glass($id, "Glass", $glassBreakInfo));
self::register("glass_pane", fn(BID $id) => new GlassPane($id, "Glass Pane", $glassBreakInfo));
- self::register("glowing_obsidian", fn(BID $id) => new GlowingObsidian($id, "Glowing Obsidian", new Info(BreakInfo::pickaxe(10.0, ToolTier::DIAMOND, 50.0))));
+ self::register("glowing_obsidian", fn(BID $id) => new GlowingObsidian($id, "Glowing Obsidian", new Info(BreakInfo::pickaxe(35.0, ToolTier::DIAMOND, 6000.0))));
self::register("glowstone", fn(BID $id) => new Glowstone($id, "Glowstone", new Info(BreakInfo::pickaxe(0.3))));
- self::register("glow_lichen", fn(BID $id) => new GlowLichen($id, "Glow Lichen", new Info(BreakInfo::axe(0.2, null, 0.2))));
+ self::register("glow_lichen", fn(BID $id) => new GlowLichen($id, "Glow Lichen", new Info(BreakInfo::axe(0.2))));
self::register("gold", fn(BID $id) => new Opaque($id, "Gold Block", new Info(BreakInfo::pickaxe(3.0, ToolTier::IRON, 30.0))));
- $grassBreakInfo = BreakInfo::shovel(0.6);
- self::register("grass", fn(BID $id) => new Grass($id, "Grass", new Info($grassBreakInfo, [Tags::DIRT])));
- self::register("grass_path", fn(BID $id) => new GrassPath($id, "Grass Path", new Info($grassBreakInfo)));
+ self::register("grass", fn(BID $id) => new Grass($id, "Grass", new Info(BreakInfo::shovel(0.6), [Tags::DIRT])));
+ self::register("grass_path", fn(BID $id) => new GrassPath($id, "Grass Path", new Info(BreakInfo::shovel(0.65))));
self::register("gravel", fn(BID $id) => new Gravel($id, "Gravel", new Info(BreakInfo::shovel(0.6))));
- $hardenedClayBreakInfo = new Info(BreakInfo::pickaxe(1.25, ToolTier::WOOD, 21.0));
- self::register("hardened_clay", fn(BID $id) => new HardenedClay($id, "Hardened Clay", $hardenedClayBreakInfo));
+ self::register("hardened_clay", fn(BID $id) => new HardenedClay($id, "Hardened Clay", new Info(BreakInfo::pickaxe(1.25, ToolTier::WOOD, 21.0))));
$hardenedGlassBreakInfo = new Info(new BreakInfo(10.0));
self::register("hardened_glass", fn(BID $id) => new HardenedGlass($id, "Hardened Glass", $hardenedGlassBreakInfo));
self::register("hardened_glass_pane", fn(BID $id) => new HardenedGlassPane($id, "Hardened Glass Pane", $hardenedGlassBreakInfo));
self::register("hay_bale", fn(BID $id) => new HayBale($id, "Hay Bale", new Info(new BreakInfo(0.5))));
- self::register("hopper", fn(BID $id) => new Hopper($id, "Hopper", new Info(BreakInfo::pickaxe(3.0, ToolTier::WOOD, 15.0))), TileHopper::class);
+ self::register("hopper", fn(BID $id) => new Hopper($id, "Hopper", new Info(BreakInfo::pickaxe(3.0, ToolTier::WOOD, 24.0))), TileHopper::class);
self::register("ice", fn(BID $id) => new Ice($id, "Ice", new Info(BreakInfo::pickaxe(0.5))));
$updateBlockBreakInfo = new Info(new BreakInfo(1.0));
self::register("info_update", fn(BID $id) => new Opaque($id, "update!", $updateBlockBreakInfo));
self::register("info_update2", fn(BID $id) => new Opaque($id, "ate!upd", $updateBlockBreakInfo));
- self::register("invisible_bedrock", fn(BID $id) => new Transparent($id, "Invisible Bedrock", new Info(BreakInfo::indestructible())));
+ self::register("invisible_bedrock", fn(BID $id) => new Transparent($id, "Invisible Bedrock", new Info(BreakInfo::indestructible(18000000.0))));
$ironBreakInfo = new Info(BreakInfo::pickaxe(5.0, ToolTier::STONE, 30.0));
self::register("iron", fn(BID $id) => new Opaque($id, "Iron Block", $ironBreakInfo));
@@ -1006,16 +1043,16 @@ final class VanillaBlocks{
self::register("item_frame", fn(BID $id) => new ItemFrame($id, "Item Frame", $itemFrameInfo), TileItemFrame::class);
self::register("glowing_item_frame", fn(BID $id) => new ItemFrame($id, "Glow Item Frame", $itemFrameInfo), TileGlowingItemFrame::class);
- self::register("jukebox", fn(BID $id) => new Jukebox($id, "Jukebox", new Info(BreakInfo::axe(0.8))), TileJukebox::class); //TODO: in PC the hardness is 2.0, not 0.8, unsure if this is a MCPE bug or not
+ self::register("jukebox", fn(BID $id) => new Jukebox($id, "Jukebox", new Info(BreakInfo::axe(2.0, blastResistance: 30.0))), TileJukebox::class);
self::register("ladder", fn(BID $id) => new Ladder($id, "Ladder", new Info(BreakInfo::axe(0.4))));
- $lanternBreakInfo = new Info(BreakInfo::pickaxe(5.0));
+ $lanternBreakInfo = new Info(BreakInfo::pickaxe(3.5));
self::register("lantern", fn(BID $id) => new Lantern($id, "Lantern", $lanternBreakInfo, 15));
self::register("soul_lantern", fn(BID $id) => new Lantern($id, "Soul Lantern", $lanternBreakInfo, 10));
self::register("lapis_lazuli", fn(BID $id) => new Opaque($id, "Lapis Lazuli Block", new Info(BreakInfo::pickaxe(3.0, ToolTier::STONE))));
self::register("lava", fn(BID $id) => new Lava($id, "Lava", new Info(BreakInfo::indestructible(500.0))));
- self::register("lectern", fn(BID $id) => new Lectern($id, "Lectern", new Info(BreakInfo::axe(2.0))), TileLectern::class);
+ self::register("lectern", fn(BID $id) => new Lectern($id, "Lectern", new Info(BreakInfo::axe(2.5))), TileLectern::class);
self::register("lever", fn(BID $id) => new Lever($id, "Lever", new Info(new BreakInfo(0.5))));
self::register("magma", fn(BID $id) => new Magma($id, "Magma Block", new Info(BreakInfo::pickaxe(0.5, ToolTier::WOOD))));
self::register("melon", fn(BID $id) => new Melon($id, "Melon Block", new Info(BreakInfo::axe(1.0))));
@@ -1065,14 +1102,15 @@ final class VanillaBlocks{
self::register("purpur_stairs", fn(BID $id) => new Stair($id, "Purpur Stairs", $purpurBreakInfo));
$quartzBreakInfo = new Info(BreakInfo::pickaxe(0.8, ToolTier::WOOD));
+ $smoothQuartzBreakInfo = new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0));
self::register("quartz", fn(BID $id) => new Opaque($id, "Quartz Block", $quartzBreakInfo));
self::register("chiseled_quartz", fn(BID $id) => new SimplePillar($id, "Chiseled Quartz Block", $quartzBreakInfo));
self::register("quartz_pillar", fn(BID $id) => new SimplePillar($id, "Quartz Pillar", $quartzBreakInfo));
- self::register("smooth_quartz", fn(BID $id) => new Opaque($id, "Smooth Quartz Block", $quartzBreakInfo));
+ self::register("smooth_quartz", fn(BID $id) => new Opaque($id, "Smooth Quartz Block", $smoothQuartzBreakInfo));
self::register("quartz_bricks", fn(BID $id) => new Opaque($id, "Quartz Bricks", $quartzBreakInfo));
self::register("quartz_stairs", fn(BID $id) => new Stair($id, "Quartz Stairs", $quartzBreakInfo));
- self::register("smooth_quartz_stairs", fn(BID $id) => new Stair($id, "Smooth Quartz Stairs", $quartzBreakInfo));
+ self::register("smooth_quartz_stairs", fn(BID $id) => new Stair($id, "Smooth Quartz Stairs", $smoothQuartzBreakInfo));
self::register("rail", fn(BID $id) => new Rail($id, "Rail", $railBreakInfo));
self::register("red_mushroom", fn(BID $id) => new RedMushroom($id, "Red Mushroom", new Info(BreakInfo::instant(), [Tags::POTTABLE_PLANTS])));
@@ -1127,13 +1165,13 @@ final class VanillaBlocks{
$infestedStoneBreakInfo = new Info(BreakInfo::pickaxe(0.75));
self::register("infested_stone", fn(BID $id) => new InfestedStone($id, "Infested Stone", $infestedStoneBreakInfo, $stone));
self::register("infested_stone_brick", fn(BID $id) => new InfestedStone($id, "Infested Stone Brick", $infestedStoneBreakInfo, $stoneBrick));
- self::register("infested_cobblestone", fn(BID $id) => new InfestedStone($id, "Infested Cobblestone", $infestedStoneBreakInfo, $cobblestone));
+ self::register("infested_cobblestone", fn(BID $id) => new InfestedStone($id, "Infested Cobblestone", new Info(BreakInfo::pickaxe(1.0, blastResistance: 3.75)), $cobblestone));
self::register("infested_mossy_stone_brick", fn(BID $id) => new InfestedStone($id, "Infested Mossy Stone Brick", $infestedStoneBreakInfo, $mossyStoneBrick));
self::register("infested_cracked_stone_brick", fn(BID $id) => new InfestedStone($id, "Infested Cracked Stone Brick", $infestedStoneBreakInfo, $crackedStoneBrick));
self::register("infested_chiseled_stone_brick", fn(BID $id) => new InfestedStone($id, "Infested Chiseled Stone Brick", $infestedStoneBreakInfo, $chiseledStoneBrick));
self::register("stone_stairs", fn(BID $id) => new Stair($id, "Stone Stairs", $stoneBreakInfo));
- self::register("smooth_stone", fn(BID $id) => new Opaque($id, "Smooth Stone", $stoneBreakInfo));
+ self::register("smooth_stone", fn(BID $id) => new Opaque($id, "Smooth Stone", new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0))));
self::register("andesite_stairs", fn(BID $id) => new Stair($id, "Andesite Stairs", $stoneBreakInfo));
self::register("diorite_stairs", fn(BID $id) => new Stair($id, "Diorite Stairs", $stoneBreakInfo));
self::register("granite_stairs", fn(BID $id) => new Stair($id, "Granite Stairs", $stoneBreakInfo));
@@ -1146,7 +1184,6 @@ final class VanillaBlocks{
self::register("stonecutter", fn(BID $id) => new Stonecutter($id, "Stonecutter", new Info(BreakInfo::pickaxe(3.5))));
self::register("stone_pressure_plate", fn(BID $id) => new StonePressurePlate($id, "Stone Pressure Plate", new Info(BreakInfo::pickaxe(0.5))));
- //TODO: in the future this won't be the same for all the types
$stoneSlabBreakInfo = new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0));
self::register("brick_slab", fn(BID $id) => new Slab($id, "Brick", $stoneSlabBreakInfo));
@@ -1157,28 +1194,31 @@ final class VanillaBlocks{
self::register("sandstone_slab", fn(BID $id) => new Slab($id, "Sandstone", $stoneSlabBreakInfo));
self::register("smooth_stone_slab", fn(BID $id) => new Slab($id, "Smooth Stone", $stoneSlabBreakInfo));
self::register("stone_brick_slab", fn(BID $id) => new Slab($id, "Stone Brick", $stoneSlabBreakInfo));
- self::register("dark_prismarine_slab", fn(BID $id) => new Slab($id, "Dark Prismarine", $stoneSlabBreakInfo));
- self::register("mossy_cobblestone_slab", fn(BID $id) => new Slab($id, "Mossy Cobblestone", $stoneSlabBreakInfo));
- self::register("prismarine_slab", fn(BID $id) => new Slab($id, "Prismarine", $stoneSlabBreakInfo));
- self::register("prismarine_bricks_slab", fn(BID $id) => new Slab($id, "Prismarine Bricks", $stoneSlabBreakInfo));
- self::register("purpur_slab", fn(BID $id) => new Slab($id, "Purpur", $stoneSlabBreakInfo));
self::register("red_nether_brick_slab", fn(BID $id) => new Slab($id, "Red Nether Brick", $stoneSlabBreakInfo));
self::register("red_sandstone_slab", fn(BID $id) => new Slab($id, "Red Sandstone", $stoneSlabBreakInfo));
self::register("smooth_sandstone_slab", fn(BID $id) => new Slab($id, "Smooth Sandstone", $stoneSlabBreakInfo));
- self::register("andesite_slab", fn(BID $id) => new Slab($id, "Andesite", $stoneSlabBreakInfo));
- self::register("diorite_slab", fn(BID $id) => new Slab($id, "Diorite", $stoneSlabBreakInfo));
- self::register("end_stone_brick_slab", fn(BID $id) => new Slab($id, "End Stone Brick", $stoneSlabBreakInfo));
- self::register("granite_slab", fn(BID $id) => new Slab($id, "Granite", $stoneSlabBreakInfo));
- self::register("polished_andesite_slab", fn(BID $id) => new Slab($id, "Polished Andesite", $stoneSlabBreakInfo));
- self::register("polished_diorite_slab", fn(BID $id) => new Slab($id, "Polished Diorite", $stoneSlabBreakInfo));
- self::register("polished_granite_slab", fn(BID $id) => new Slab($id, "Polished Granite", $stoneSlabBreakInfo));
- self::register("smooth_red_sandstone_slab", fn(BID $id) => new Slab($id, "Smooth Red Sandstone", $stoneSlabBreakInfo));
self::register("cut_red_sandstone_slab", fn(BID $id) => new Slab($id, "Cut Red Sandstone", $stoneSlabBreakInfo));
self::register("cut_sandstone_slab", fn(BID $id) => new Slab($id, "Cut Sandstone", $stoneSlabBreakInfo));
- self::register("mossy_stone_brick_slab", fn(BID $id) => new Slab($id, "Mossy Stone Brick", $stoneSlabBreakInfo));
+ self::register("mossy_cobblestone_slab", fn(BID $id) => new Slab($id, "Mossy Cobblestone", $stoneSlabBreakInfo));
+ self::register("purpur_slab", fn(BID $id) => new Slab($id, "Purpur", $stoneSlabBreakInfo));
+ self::register("smooth_red_sandstone_slab", fn(BID $id) => new Slab($id, "Smooth Red Sandstone", $stoneSlabBreakInfo));
self::register("smooth_quartz_slab", fn(BID $id) => new Slab($id, "Smooth Quartz", $stoneSlabBreakInfo));
self::register("stone_slab", fn(BID $id) => new Slab($id, "Stone", $stoneSlabBreakInfo));
+ self::register("end_stone_brick_slab", fn(BID $id) => new Slab($id, "End Stone Brick", new Info(BreakInfo::pickaxe(3.0, ToolTier::WOOD, 30.0))));
+
+ $lightStoneSlabBreakInfo = new Info(BreakInfo::pickaxe(1.5, ToolTier::WOOD, 30.0));
+ self::register("dark_prismarine_slab", fn(BID $id) => new Slab($id, "Dark Prismarine", $lightStoneSlabBreakInfo));
+ self::register("prismarine_slab", fn(BID $id) => new Slab($id, "Prismarine", $lightStoneSlabBreakInfo));
+ self::register("prismarine_bricks_slab", fn(BID $id) => new Slab($id, "Prismarine Bricks", $lightStoneSlabBreakInfo));
+ self::register("andesite_slab", fn(BID $id) => new Slab($id, "Andesite", $lightStoneSlabBreakInfo));
+ self::register("diorite_slab", fn(BID $id) => new Slab($id, "Diorite", $lightStoneSlabBreakInfo));
+ self::register("granite_slab", fn(BID $id) => new Slab($id, "Granite", $lightStoneSlabBreakInfo));
+ self::register("polished_andesite_slab", fn(BID $id) => new Slab($id, "Polished Andesite", $lightStoneSlabBreakInfo));
+ self::register("polished_diorite_slab", fn(BID $id) => new Slab($id, "Polished Diorite", $lightStoneSlabBreakInfo));
+ self::register("polished_granite_slab", fn(BID $id) => new Slab($id, "Polished Granite", $lightStoneSlabBreakInfo));
+ self::register("mossy_stone_brick_slab", fn(BID $id) => new Slab($id, "Mossy Stone Brick", $lightStoneSlabBreakInfo));
+
self::register("legacy_stonecutter", fn(BID $id) => new Opaque($id, "Legacy Stonecutter", new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD))));
self::register("sugarcane", fn(BID $id) => new Sugarcane($id, "Sugarcane", new Info(BreakInfo::instant())));
self::register("sweet_berry_bush", fn(BID $id) => new SweetBerryBush($id, "Sweet Berry Bush", new Info(BreakInfo::instant())));
@@ -1237,25 +1277,26 @@ final class VanillaBlocks{
}
$sandstoneBreakInfo = new Info(BreakInfo::pickaxe(0.8, ToolTier::WOOD));
+ $smoothSandstoneBreakInfo = new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0));
self::register("red_sandstone_stairs", fn(BID $id) => new Stair($id, "Red Sandstone Stairs", $sandstoneBreakInfo));
- self::register("smooth_red_sandstone_stairs", fn(BID $id) => new Stair($id, "Smooth Red Sandstone Stairs", $sandstoneBreakInfo));
+ self::register("smooth_red_sandstone_stairs", fn(BID $id) => new Stair($id, "Smooth Red Sandstone Stairs", $smoothSandstoneBreakInfo));
self::register("red_sandstone", fn(BID $id) => new Opaque($id, "Red Sandstone", $sandstoneBreakInfo));
self::register("chiseled_red_sandstone", fn(BID $id) => new Opaque($id, "Chiseled Red Sandstone", $sandstoneBreakInfo));
self::register("cut_red_sandstone", fn(BID $id) => new Opaque($id, "Cut Red Sandstone", $sandstoneBreakInfo));
- self::register("smooth_red_sandstone", fn(BID $id) => new Opaque($id, "Smooth Red Sandstone", $sandstoneBreakInfo));
+ self::register("smooth_red_sandstone", fn(BID $id) => new Opaque($id, "Smooth Red Sandstone", $smoothSandstoneBreakInfo));
self::register("sandstone_stairs", fn(BID $id) => new Stair($id, "Sandstone Stairs", $sandstoneBreakInfo));
- self::register("smooth_sandstone_stairs", fn(BID $id) => new Stair($id, "Smooth Sandstone Stairs", $sandstoneBreakInfo));
+ self::register("smooth_sandstone_stairs", fn(BID $id) => new Stair($id, "Smooth Sandstone Stairs", $smoothSandstoneBreakInfo));
self::register("sandstone", fn(BID $id) => new Opaque($id, "Sandstone", $sandstoneBreakInfo));
self::register("chiseled_sandstone", fn(BID $id) => new Opaque($id, "Chiseled Sandstone", $sandstoneBreakInfo));
self::register("cut_sandstone", fn(BID $id) => new Opaque($id, "Cut Sandstone", $sandstoneBreakInfo));
- self::register("smooth_sandstone", fn(BID $id) => new Opaque($id, "Smooth Sandstone", $sandstoneBreakInfo));
+ self::register("smooth_sandstone", fn(BID $id) => new Opaque($id, "Smooth Sandstone", $smoothSandstoneBreakInfo));
self::register("glazed_terracotta", fn(BID $id) => new GlazedTerracotta($id, "Glazed Terracotta", new Info(BreakInfo::pickaxe(1.4, ToolTier::WOOD))));
self::register("dyed_shulker_box", fn(BID $id) => new DyedShulkerBox($id, "Dyed Shulker Box", $shulkerBoxBreakInfo), TileShulkerBox::class);
self::register("stained_glass", fn(BID $id) => new StainedGlass($id, "Stained Glass", $glassBreakInfo));
self::register("stained_glass_pane", fn(BID $id) => new StainedGlassPane($id, "Stained Glass Pane", $glassBreakInfo));
- self::register("stained_clay", fn(BID $id) => new StainedHardenedClay($id, "Stained Clay", $hardenedClayBreakInfo));
+ self::register("stained_clay", fn(BID $id) => new StainedHardenedClay($id, "Stained Clay", new Info(BreakInfo::pickaxe(1.25, ToolTier::WOOD, 6.25))));
self::register("stained_hardened_glass", fn(BID $id) => new StainedHardenedGlass($id, "Stained Hardened Glass", $hardenedGlassBreakInfo));
self::register("stained_hardened_glass_pane", fn(BID $id) => new StainedHardenedGlassPane($id, "Stained Hardened Glass Pane", $hardenedGlassBreakInfo));
self::register("carpet", fn(BID $id) => new Carpet($id, "Carpet", new Info(new BreakInfo(0.1))));
@@ -1272,22 +1313,26 @@ final class VanillaBlocks{
}
})));
- //TODO: in the future these won't all have the same hardness; they only do now because of the old metadata crap
- $wallBreakInfo = new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0));
- self::register("cobblestone_wall", fn(BID $id) => new Wall($id, "Cobblestone Wall", $wallBreakInfo));
- self::register("andesite_wall", fn(BID $id) => new Wall($id, "Andesite Wall", $wallBreakInfo));
- self::register("brick_wall", fn(BID $id) => new Wall($id, "Brick Wall", $wallBreakInfo));
- self::register("diorite_wall", fn(BID $id) => new Wall($id, "Diorite Wall", $wallBreakInfo));
- self::register("end_stone_brick_wall", fn(BID $id) => new Wall($id, "End Stone Brick Wall", $wallBreakInfo));
- self::register("granite_wall", fn(BID $id) => new Wall($id, "Granite Wall", $wallBreakInfo));
- self::register("mossy_stone_brick_wall", fn(BID $id) => new Wall($id, "Mossy Stone Brick Wall", $wallBreakInfo));
- self::register("mossy_cobblestone_wall", fn(BID $id) => new Wall($id, "Mossy Cobblestone Wall", $wallBreakInfo));
- self::register("nether_brick_wall", fn(BID $id) => new Wall($id, "Nether Brick Wall", $wallBreakInfo));
- self::register("prismarine_wall", fn(BID $id) => new Wall($id, "Prismarine Wall", $wallBreakInfo));
- self::register("red_nether_brick_wall", fn(BID $id) => new Wall($id, "Red Nether Brick Wall", $wallBreakInfo));
- self::register("red_sandstone_wall", fn(BID $id) => new Wall($id, "Red Sandstone Wall", $wallBreakInfo));
- self::register("sandstone_wall", fn(BID $id) => new Wall($id, "Sandstone Wall", $wallBreakInfo));
- self::register("stone_brick_wall", fn(BID $id) => new Wall($id, "Stone Brick Wall", $wallBreakInfo));
+ self::register("end_stone_brick_wall", fn(BID $id) => new Wall($id, "End Stone Brick Wall", new Info(BreakInfo::pickaxe(3.0, ToolTier::WOOD, 45.0))));
+
+ $brickWallBreakInfo = new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0));
+ self::register("cobblestone_wall", fn(BID $id) => new Wall($id, "Cobblestone Wall", $brickWallBreakInfo));
+ self::register("brick_wall", fn(BID $id) => new Wall($id, "Brick Wall", $brickWallBreakInfo));
+ self::register("mossy_cobblestone_wall", fn(BID $id) => new Wall($id, "Mossy Cobblestone Wall", $brickWallBreakInfo));
+ self::register("nether_brick_wall", fn(BID $id) => new Wall($id, "Nether Brick Wall", $brickWallBreakInfo));
+ self::register("red_nether_brick_wall", fn(BID $id) => new Wall($id, "Red Nether Brick Wall", $brickWallBreakInfo));
+
+ $stoneWallBreakInfo = new Info(BreakInfo::pickaxe(1.5, ToolTier::WOOD, 30.0));
+ self::register("stone_brick_wall", fn(BID $id) => new Wall($id, "Stone Brick Wall", $stoneWallBreakInfo));
+ self::register("mossy_stone_brick_wall", fn(BID $id) => new Wall($id, "Mossy Stone Brick Wall", $stoneWallBreakInfo));
+ self::register("granite_wall", fn(BID $id) => new Wall($id, "Granite Wall", $stoneWallBreakInfo));
+ self::register("diorite_wall", fn(BID $id) => new Wall($id, "Diorite Wall", $stoneWallBreakInfo));
+ self::register("andesite_wall", fn(BID $id) => new Wall($id, "Andesite Wall", $stoneWallBreakInfo));
+ self::register("prismarine_wall", fn(BID $id) => new Wall($id, "Prismarine Wall", $stoneWallBreakInfo));
+
+ $sandstoneWallBreakInfo = new Info(BreakInfo::pickaxe(0.8, ToolTier::WOOD, 4.0));
+ self::register("red_sandstone_wall", fn(BID $id) => new Wall($id, "Red Sandstone Wall", $sandstoneWallBreakInfo));
+ self::register("sandstone_wall", fn(BID $id) => new Wall($id, "Sandstone Wall", $sandstoneWallBreakInfo));
self::registerElements();
@@ -1320,8 +1365,8 @@ final class VanillaBlocks{
self::register("mangrove_roots", fn(BID $id) => new MangroveRoots($id, "Mangrove Roots", new Info(BreakInfo::axe(0.7))));
self::register("muddy_mangrove_roots", fn(BID $id) => new SimplePillar($id, "Muddy Mangrove Roots", new Info(BreakInfo::shovel(0.7), [Tags::MUD])));
self::register("froglight", fn(BID $id) => new Froglight($id, "Froglight", new Info(new BreakInfo(0.3))));
- self::register("sculk", fn(BID $id) => new Sculk($id, "Sculk", new Info(new BreakInfo(0.6, ToolType::HOE))));
- self::register("reinforced_deepslate", fn(BID $id) => new class($id, "Reinforced Deepslate", new Info(new BreakInfo(55.0, ToolType::NONE, 0, 3600.0))) extends Opaque{
+ self::register("sculk", fn(BID $id) => new Sculk($id, "Sculk", new Info(new BreakInfo(0.2, ToolType::HOE))));
+ self::register("reinforced_deepslate", fn(BID $id) => new class($id, "Reinforced Deepslate", new Info(new BreakInfo(55.0, ToolType::NONE, 0, 6000.0))) extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
@@ -1346,6 +1391,7 @@ final class VanillaBlocks{
private static function registerWoodenBlocks() : void{
$planksBreakInfo = new Info(BreakInfo::axe(2.0, null, 15.0));
$signBreakInfo = new Info(BreakInfo::axe(1.0));
+ $hangingSignBreakInfo = new Info(BreakInfo::axe(1.0), [Tags::HANGING_SIGN]);
$logBreakInfo = new Info(BreakInfo::axe(2.0));
$woodenDoorBreakInfo = new Info(BreakInfo::axe(3.0, null, 15.0));
$woodenButtonBreakInfo = new Info(BreakInfo::axe(0.5));
@@ -1385,6 +1431,23 @@ final class VanillaBlocks{
};
self::register($idName("sign"), fn(BID $id) => new FloorSign($id, $name . " Sign", $signBreakInfo, $woodType, $signAsItem), TileSign::class);
self::register($idName("wall_sign"), fn(BID $id) => new WallSign($id, $name . " Wall Sign", $signBreakInfo, $woodType, $signAsItem), TileSign::class);
+
+ $hangingSignAsItem = match($woodType){
+ WoodType::OAK => VanillaItems::OAK_HANGING_SIGN(...),
+ WoodType::SPRUCE => VanillaItems::SPRUCE_HANGING_SIGN(...),
+ WoodType::BIRCH => VanillaItems::BIRCH_HANGING_SIGN(...),
+ WoodType::JUNGLE => VanillaItems::JUNGLE_HANGING_SIGN(...),
+ WoodType::ACACIA => VanillaItems::ACACIA_HANGING_SIGN(...),
+ WoodType::DARK_OAK => VanillaItems::DARK_OAK_HANGING_SIGN(...),
+ WoodType::MANGROVE => VanillaItems::MANGROVE_HANGING_SIGN(...),
+ WoodType::CRIMSON => VanillaItems::CRIMSON_HANGING_SIGN(...),
+ WoodType::WARPED => VanillaItems::WARPED_HANGING_SIGN(...),
+ WoodType::CHERRY => VanillaItems::CHERRY_HANGING_SIGN(...),
+ WoodType::PALE_OAK => VanillaItems::PALE_OAK_HANGING_SIGN(...),
+ };
+ self::register($idName("ceiling_center_hanging_sign"), fn(BID $id) => new CeilingCenterHangingSign($id, $name . " Center Hanging Sign", $hangingSignBreakInfo, $woodType, $hangingSignAsItem), TileHangingSign::class);
+ self::register($idName("ceiling_edges_hanging_sign"), fn(BID $id) => new CeilingEdgesHangingSign($id, $name . " Edges Hanging Sign", $hangingSignBreakInfo, $woodType, $hangingSignAsItem), TileHangingSign::class);
+ self::register($idName("wall_hanging_sign"), fn(BID $id) => new WallHangingSign($id, $name . " Wall Hanging Sign", $hangingSignBreakInfo, $woodType, $hangingSignAsItem), TileHangingSign::class);
}
}
@@ -1537,7 +1600,7 @@ final class VanillaBlocks{
self::register("lapis_lazuli_ore", fn(BID $id) => new LapisOre($id, "Lapis Lazuli Ore", $stoneOreBreakInfo(ToolTier::STONE)));
self::register("redstone_ore", fn(BID $id) => new RedstoneOre($id, "Redstone Ore", $stoneOreBreakInfo(ToolTier::IRON)));
- $deepslateOreBreakInfo = fn(ToolTier $toolTier) => new Info(BreakInfo::pickaxe(4.5, $toolTier));
+ $deepslateOreBreakInfo = fn(ToolTier $toolTier) => new Info(BreakInfo::pickaxe(4.5, $toolTier, 15.0));
self::register("deepslate_coal_ore", fn(BID $id) => new CoalOre($id, "Deepslate Coal Ore", $deepslateOreBreakInfo(ToolTier::WOOD)));
self::register("deepslate_copper_ore", fn(BID $id) => new CopperOre($id, "Deepslate Copper Ore", $deepslateOreBreakInfo(ToolTier::STONE)));
self::register("deepslate_diamond_ore", fn(BID $id) => new DiamondOre($id, "Deepslate Diamond Ore", $deepslateOreBreakInfo(ToolTier::IRON)));
@@ -1581,10 +1644,10 @@ final class VanillaBlocks{
//for some reason, slabs have weird hardness like the legacy ones
$slabBreakInfo = new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0));
- self::register("ancient_debris", fn(BID $id) => new class($id, "Ancient Debris", new Info(BreakInfo::pickaxe(30, ToolTier::DIAMOND, 3600.0))) extends Opaque{
+ self::register("ancient_debris", fn(BID $id) => new class($id, "Ancient Debris", new Info(BreakInfo::pickaxe(30, ToolTier::DIAMOND, 6000.0))) extends Opaque{
public function isFireProofAsItem() : bool{ return true; }
});
- $netheriteBreakInfo = new Info(BreakInfo::pickaxe(50, ToolTier::DIAMOND, 3600.0));
+ $netheriteBreakInfo = new Info(BreakInfo::pickaxe(50, ToolTier::DIAMOND, 6000.0));
self::register("netherite", fn(BID $id) => new class($id, "Netherite Block", $netheriteBreakInfo) extends Opaque{
public function isFireProofAsItem() : bool{ return true; }
});
@@ -1602,14 +1665,14 @@ final class VanillaBlocks{
self::register("gilded_blackstone", fn(BID $id) => new GildedBlackstone($id, "Gilded Blackstone", $blackstoneBreakInfo));
- //TODO: polished blackstone ought to have 2.0 hardness (as per java) but it's 1.5 in Bedrock (probably parity bug)
+ $polishedBlackstoneBreakInfo = new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0));
$prefix = fn(string $thing) => "Polished Blackstone" . ($thing !== "" ? " $thing" : "");
- self::register("polished_blackstone", fn(BID $id) => new Opaque($id, $prefix(""), $blackstoneBreakInfo));
+ self::register("polished_blackstone", fn(BID $id) => new Opaque($id, $prefix(""), $polishedBlackstoneBreakInfo));
self::register("polished_blackstone_button", fn(BID $id) => new StoneButton($id, $prefix("Button"), new Info(BreakInfo::pickaxe(0.5))));
self::register("polished_blackstone_pressure_plate", fn(BID $id) => new StonePressurePlate($id, $prefix("Pressure Plate"), new Info(BreakInfo::pickaxe(0.5)), 20));
self::register("polished_blackstone_slab", fn(BID $id) => new Slab($id, $prefix(""), $slabBreakInfo));
- self::register("polished_blackstone_stairs", fn(BID $id) => new Stair($id, $prefix("Stairs"), $blackstoneBreakInfo));
- self::register("polished_blackstone_wall", fn(BID $id) => new Wall($id, $prefix("Wall"), $blackstoneBreakInfo));
+ self::register("polished_blackstone_stairs", fn(BID $id) => new Stair($id, $prefix("Stairs"), $polishedBlackstoneBreakInfo));
+ self::register("polished_blackstone_wall", fn(BID $id) => new Wall($id, $prefix("Wall"), $polishedBlackstoneBreakInfo));
self::register("chiseled_polished_blackstone", fn(BID $id) => new Opaque($id, "Chiseled Polished Blackstone", $blackstoneBreakInfo));
$prefix = fn(string $thing) => "Polished Blackstone Brick" . ($thing !== "" ? " $thing" : "");
@@ -1622,8 +1685,7 @@ final class VanillaBlocks{
self::register("soul_torch", fn(BID $id) => new Torch($id, "Soul Torch", new Info(BreakInfo::instant())));
self::register("soul_fire", fn(BID $id) => new SoulFire($id, "Soul Fire", new Info(BreakInfo::instant(), [Tags::FIRE])));
- //TODO: soul soul ought to have 0.5 hardness (as per java) but it's 1.0 in Bedrock (probably parity bug)
- self::register("soul_soil", fn(BID $id) => new Opaque($id, "Soul Soil", new Info(BreakInfo::shovel(1.0))));
+ self::register("soul_soil", fn(BID $id) => new Opaque($id, "Soul Soil", new Info(BreakInfo::shovel(0.5))));
self::register("shroomlight", fn(BID $id) => new class($id, "Shroomlight", new Info(new BreakInfo(1.0, ToolType::HOE))) extends Opaque{
public function getLightLevel() : int{ return 15; }
@@ -1641,7 +1703,9 @@ final class VanillaBlocks{
self::register("crimson_roots", fn(BID $id) => new NetherRoots($id, "Crimson Roots", $netherRootsInfo));
self::register("warped_roots", fn(BID $id) => new NetherRoots($id, "Warped Roots", $netherRootsInfo));
- self::register("chain", fn(BID $id) => new Chain($id, "Chain", new Info(BreakInfo::pickaxe(5.0, ToolTier::WOOD))));
+ self::register("chain", fn(BID $id) => new Chain($id, "Chain", new Info(BreakInfo::pickaxe(5.0, ToolTier::WOOD, 30.0))));
+
+ self::register("respawn_anchor", fn(BID $id) => new RespawnAnchor($id, "Respawn Anchor", new Info(BreakInfo::pickaxe(50.0, ToolTier::DIAMOND, 6000.0))));
}
private static function registerBlocksR17() : void{
@@ -1659,7 +1723,7 @@ final class VanillaBlocks{
self::register("raw_gold", fn(BID $id) => new Opaque($id, "Raw Gold Block", new Info(BreakInfo::pickaxe(5, ToolTier::IRON, 30.0))));
self::register("raw_iron", fn(BID $id) => new Opaque($id, "Raw Iron Block", new Info(BreakInfo::pickaxe(5, ToolTier::STONE, 30.0))));
- $deepslateBreakInfo = new Info(BreakInfo::pickaxe(3, ToolTier::WOOD, 18.0));
+ $deepslateBreakInfo = new Info(BreakInfo::pickaxe(3, ToolTier::WOOD, 30.0));
self::register("deepslate", fn(BID $id) => new class($id, "Deepslate", $deepslateBreakInfo) extends SimplePillar{
public function getDropsForCompatibleTool(Item $item) : array{
return [VanillaBlocks::COBBLED_DEEPSLATE()->asItem()];
@@ -1671,29 +1735,29 @@ final class VanillaBlocks{
});
//TODO: parity issue here - in Java this has a hardness of 3.0, but in bedrock it's 3.5
- self::register("chiseled_deepslate", fn(BID $id) => new Opaque($id, "Chiseled Deepslate", new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD, 18.0))));
+ self::register("chiseled_deepslate", fn(BID $id) => new Opaque($id, "Chiseled Deepslate", new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD, 30.0))));
- $deepslateBrickBreakInfo = new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD, 18.0));
+ $deepslateBrickBreakInfo = new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD, 30.0));
self::register("deepslate_bricks", fn(BID $id) => new Opaque($id, "Deepslate Bricks", $deepslateBrickBreakInfo));
self::register("deepslate_brick_slab", fn(BID $id) => new Slab($id, "Deepslate Brick", $deepslateBrickBreakInfo));
self::register("deepslate_brick_stairs", fn(BID $id) => new Stair($id, "Deepslate Brick Stairs", $deepslateBrickBreakInfo));
self::register("deepslate_brick_wall", fn(BID $id) => new Wall($id, "Deepslate Brick Wall", $deepslateBrickBreakInfo));
self::register("cracked_deepslate_bricks", fn(BID $id) => new Opaque($id, "Cracked Deepslate Bricks", $deepslateBrickBreakInfo));
- $deepslateTilesBreakInfo = new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD, 18.0));
+ $deepslateTilesBreakInfo = new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD, 30.0));
self::register("deepslate_tiles", fn(BID $id) => new Opaque($id, "Deepslate Tiles", $deepslateTilesBreakInfo));
self::register("deepslate_tile_slab", fn(BID $id) => new Slab($id, "Deepslate Tile", $deepslateTilesBreakInfo));
self::register("deepslate_tile_stairs", fn(BID $id) => new Stair($id, "Deepslate Tile Stairs", $deepslateTilesBreakInfo));
self::register("deepslate_tile_wall", fn(BID $id) => new Wall($id, "Deepslate Tile Wall", $deepslateTilesBreakInfo));
self::register("cracked_deepslate_tiles", fn(BID $id) => new Opaque($id, "Cracked Deepslate Tiles", $deepslateTilesBreakInfo));
- $cobbledDeepslateBreakInfo = new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD, 18.0));
+ $cobbledDeepslateBreakInfo = new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD, 30.0));
self::register("cobbled_deepslate", fn(BID $id) => new Opaque($id, "Cobbled Deepslate", $cobbledDeepslateBreakInfo));
self::register("cobbled_deepslate_slab", fn(BID $id) => new Slab($id, "Cobbled Deepslate", $cobbledDeepslateBreakInfo));
self::register("cobbled_deepslate_stairs", fn(BID $id) => new Stair($id, "Cobbled Deepslate Stairs", $cobbledDeepslateBreakInfo));
self::register("cobbled_deepslate_wall", fn(BID $id) => new Wall($id, "Cobbled Deepslate Wall", $cobbledDeepslateBreakInfo));
- $polishedDeepslateBreakInfo = new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD, 18.0));
+ $polishedDeepslateBreakInfo = new Info(BreakInfo::pickaxe(3.5, ToolTier::WOOD, 30.0));
self::register("polished_deepslate", fn(BID $id) => new Opaque($id, "Polished Deepslate", $polishedDeepslateBreakInfo));
self::register("polished_deepslate_slab", fn(BID $id) => new Slab($id, "Polished Deepslate", $polishedDeepslateBreakInfo));
self::register("polished_deepslate_stairs", fn(BID $id) => new Stair($id, "Polished Deepslate Stairs", $polishedDeepslateBreakInfo));
@@ -1702,7 +1766,7 @@ final class VanillaBlocks{
self::register("tinted_glass", fn(BID $id) => new TintedGlass($id, "Tinted Glass", new Info(new BreakInfo(0.3))));
//blast resistance should be 30 if we were matched with java :(
- $copperBreakInfo = new Info(BreakInfo::pickaxe(3.0, ToolTier::STONE, 18.0));
+ $copperBreakInfo = new Info(BreakInfo::pickaxe(3.0, ToolTier::STONE, 30.0));
self::register("lightning_rod", fn(BID $id) => new LightningRod($id, "Lightning Rod", $copperBreakInfo));
self::register("copper", fn(BID $id) => new Copper($id, "Copper Block", $copperBreakInfo));
@@ -1730,8 +1794,8 @@ final class VanillaBlocks{
self::register("cave_vines", fn(BID $id) => new CaveVines($id, "Cave Vines", new Info(BreakInfo::instant())));
self::register("small_dripleaf", fn(BID $id) => new SmallDripleaf($id, "Small Dripleaf", new Info(BreakInfo::instant(ToolType::SHEARS, toolHarvestLevel: 1))));
- self::register("big_dripleaf_head", fn(BID $id) => new BigDripleafHead($id, "Big Dripleaf", new Info(BreakInfo::instant())));
- self::register("big_dripleaf_stem", fn(BID $id) => new BigDripleafStem($id, "Big Dripleaf Stem", new Info(BreakInfo::instant())));
+ self::register("big_dripleaf_head", fn(BID $id) => new BigDripleafHead($id, "Big Dripleaf", new Info(new BreakInfo(0.1))));
+ self::register("big_dripleaf_stem", fn(BID $id) => new BigDripleafStem($id, "Big Dripleaf Stem", new Info(new BreakInfo(0.1))));
}
private static function registerBlocksR18() : void{
@@ -1742,7 +1806,7 @@ final class VanillaBlocks{
self::register("mud", fn(BID $id) => new Opaque($id, "Mud", new Info(BreakInfo::shovel(0.5), [Tags::MUD])));
self::register("packed_mud", fn(BID $id) => new Opaque($id, "Packed Mud", new Info(BreakInfo::pickaxe(1.0, null, 15.0))));
- $mudBricksBreakInfo = new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0));
+ $mudBricksBreakInfo = new Info(BreakInfo::pickaxe(1.5, ToolTier::WOOD, 15.0));
self::register("mud_bricks", fn(BID $id) => new Opaque($id, "Mud Bricks", $mudBricksBreakInfo));
self::register("mud_brick_slab", fn(BID $id) => new Slab($id, "Mud Brick", $mudBricksBreakInfo));
@@ -1754,7 +1818,7 @@ final class VanillaBlocks{
self::register("resin", fn(BID $id) => new Opaque($id, "Block of Resin", new Info(BreakInfo::instant())));
self::register("resin_clump", fn(BID $id) => new ResinClump($id, "Resin Clump", new Info(BreakInfo::instant())));
- $resinBricksInfo = new Info(BreakInfo::pickaxe(1.5, ToolTier::WOOD));
+ $resinBricksInfo = new Info(BreakInfo::pickaxe(1.5, ToolTier::WOOD, 30.0));
self::register("resin_brick_slab", fn(BID $id) => new Slab($id, "Resin Brick", $resinBricksInfo));
self::register("resin_brick_stairs", fn(BID $id) => new Stair($id, "Resin Brick Stairs", $resinBricksInfo));
self::register("resin_brick_wall", fn(BID $id) => new Wall($id, "Resin Brick Wall", $resinBricksInfo));
diff --git a/src/block/Vine.php b/src/block/Vine.php
index cc516bbca..0e6f83b12 100644
--- a/src/block/Vine.php
+++ b/src/block/Vine.php
@@ -23,59 +23,56 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\item\Item;
-use pocketmine\math\Axis;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use function array_intersect_key;
use function count;
+use function spl_object_id;
class Vine extends Flowable{
- /** @var int[] */
+ /** @var HorizontalFacingOption[] */
protected array $faces = [];
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacingFlags($this->faces);
+ $w->enumSet($this->faces, HorizontalFacingOption::cases());
}
- /** @return int[] */
+ /** @return HorizontalFacingOption[] */
public function getFaces() : array{ return $this->faces; }
- public function hasFace(int $face) : bool{
- return isset($this->faces[$face]);
+ public function hasFace(HorizontalFacingOption $face) : bool{
+ return isset($this->faces[spl_object_id($face)]);
}
/**
- * @param int[] $faces
- * @phpstan-param list $faces
+ * @param HorizontalFacingOption[] $faces
* @return $this
*/
public function setFaces(array $faces) : self{
$uniqueFaces = [];
foreach($faces as $face){
- if($face !== Facing::NORTH && $face !== Facing::SOUTH && $face !== Facing::WEST && $face !== Facing::EAST){
- throw new \InvalidArgumentException("Facing can only be north, east, south or west");
+ if(!$face instanceof HorizontalFacingOption){
+ throw new \InvalidArgumentException("Expected array of HorizontalFacingOption");
}
- $uniqueFaces[$face] = $face;
+ $uniqueFaces[spl_object_id($face)] = $face;
}
$this->faces = $uniqueFaces;
return $this;
}
/** @return $this */
- public function setFace(int $face, bool $value) : self{
- if($face !== Facing::NORTH && $face !== Facing::SOUTH && $face !== Facing::WEST && $face !== Facing::EAST){
- throw new \InvalidArgumentException("Facing can only be north, east, south or west");
- }
+ public function setFace(HorizontalFacingOption $face, bool $value) : self{
if($value){
- $this->faces[$face] = $face;
+ $this->faces[spl_object_id($face)] = $face;
}else{
- unset($this->faces[$face]);
+ unset($this->faces[spl_object_id($face)]);
}
return $this;
}
@@ -101,13 +98,15 @@ class Vine extends Flowable{
return [];
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
- if(!$blockReplace->getSide(Facing::opposite($face))->isFullCube() || Facing::axis($face) === Axis::Y){
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ $oppositeFace = Facing::opposite($face);
+ $hzFacing = HorizontalFacingOption::tryFromFacing($oppositeFace);
+ if($hzFacing === null || !$blockReplace->getSide($oppositeFace)->isFullCube()){
return false;
}
$this->faces = $blockReplace instanceof Vine ? $blockReplace->faces : [];
- $this->faces[Facing::opposite($face)] = Facing::opposite($face);
+ $this->faces[spl_object_id($hzFacing)] = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@@ -120,8 +119,8 @@ class Vine extends Flowable{
$supportedFaces = $up instanceof Vine ? array_intersect_key($this->faces, $up->faces) : [];
foreach($this->faces as $face){
- if(!isset($supportedFaces[$face]) && !$this->getSide($face)->isSolid()){
- unset($this->faces[$face]);
+ if(!isset($supportedFaces[spl_object_id($face)]) && !$this->getSide($face->toFacing())->isSolid()){
+ unset($this->faces[spl_object_id($face)]);
$changed = true;
}
}
diff --git a/src/block/Wall.php b/src/block/Wall.php
index 520ced8eb..b39e35c4b 100644
--- a/src/block/Wall.php
+++ b/src/block/Wall.php
@@ -31,7 +31,7 @@ use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
/**
- * @phpstan-type WallConnectionSet array
+ * @phpstan-type WallConnectionSet array, WallConnectionType>
*/
class Wall extends Transparent{
@@ -53,8 +53,8 @@ class Wall extends Transparent{
*/
public function getConnections() : array{ return $this->connections; }
- public function getConnection(int $face) : ?WallConnectionType{
- return $this->connections[$face] ?? null;
+ public function getConnection(Facing $face) : ?WallConnectionType{
+ return $this->connections[$face->value] ?? null;
}
/**
@@ -68,14 +68,14 @@ class Wall extends Transparent{
}
/** @return $this */
- public function setConnection(int $face, ?WallConnectionType $type) : self{
+ public function setConnection(Facing $face, ?WallConnectionType $type) : self{
if($face !== Facing::NORTH && $face !== Facing::SOUTH && $face !== Facing::WEST && $face !== Facing::EAST){
throw new \InvalidArgumentException("Facing can only be north, east, south or west");
}
if($type !== null){
- $this->connections[$face] = $type;
+ $this->connections[$face->value] = $type;
}else{
- unset($this->connections[$face]);
+ unset($this->connections[$face->value]);
}
return $this;
}
@@ -102,12 +102,12 @@ class Wall extends Transparent{
foreach(Facing::HORIZONTAL as $facing){
$block = $this->getSide($facing);
if($block instanceof static || $block instanceof FenceGate || $block instanceof Thin || $block->getSupportType(Facing::opposite($facing)) === SupportType::FULL){
- if(!isset($this->connections[$facing])){
- $this->connections[$facing] = WallConnectionType::SHORT;
+ if(!isset($this->connections[$facing->value])){
+ $this->connections[$facing->value] = WallConnectionType::SHORT;
$changed++;
}
- }elseif(isset($this->connections[$facing])){
- unset($this->connections[$facing]);
+ }elseif(isset($this->connections[$facing->value])){
+ unset($this->connections[$facing->value]);
$changed++;
}
}
@@ -124,10 +124,10 @@ class Wall extends Transparent{
protected function recalculateCollisionBoxes() : array{
//walls don't have any special collision boxes like fences do
- $north = isset($this->connections[Facing::NORTH]);
- $south = isset($this->connections[Facing::SOUTH]);
- $west = isset($this->connections[Facing::WEST]);
- $east = isset($this->connections[Facing::EAST]);
+ $north = isset($this->connections[Facing::NORTH->value]);
+ $south = isset($this->connections[Facing::SOUTH->value]);
+ $west = isset($this->connections[Facing::WEST->value]);
+ $east = isset($this->connections[Facing::EAST->value]);
$inset = 0.25;
if(
@@ -143,15 +143,15 @@ class Wall extends Transparent{
return [
AxisAlignedBB::one()
- ->extend(Facing::UP, 0.5)
- ->trim(Facing::NORTH, $north ? 0 : $inset)
- ->trim(Facing::SOUTH, $south ? 0 : $inset)
- ->trim(Facing::WEST, $west ? 0 : $inset)
- ->trim(Facing::EAST, $east ? 0 : $inset)
+ ->extendedCopy(Facing::UP, 0.5)
+ ->trimmedCopy(Facing::NORTH, $north ? 0 : $inset)
+ ->trimmedCopy(Facing::SOUTH, $south ? 0 : $inset)
+ ->trimmedCopy(Facing::WEST, $west ? 0 : $inset)
+ ->trimmedCopy(Facing::EAST, $east ? 0 : $inset)
];
}
- public function getSupportType(int $facing) : SupportType{
+ public function getSupportType(Facing $facing) : SupportType{
return Facing::axis($facing) === Axis::Y ? SupportType::CENTER : SupportType::NONE;
}
}
diff --git a/src/block/WallBanner.php b/src/block/WallBanner.php
index 5182fe9f8..5b3c3dc1c 100644
--- a/src/block/WallBanner.php
+++ b/src/block/WallBanner.php
@@ -23,26 +23,32 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\item\Item;
-use pocketmine\math\Axis;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-final class WallBanner extends BaseBanner{
+final class WallBanner extends BaseBanner implements HorizontalFacing{
use HorizontalFacingTrait;
- protected function getSupportingFace() : int{
- return Facing::opposite($this->facing);
+ protected function getOminousVersion() : Block{
+ return VanillaBlocks::OMINOUS_WALL_BANNER()->setFacing($this->facing);
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
- if(Facing::axis($face) === Axis::Y){
+ protected function getSupportingFace() : Facing{
+ return Facing::opposite($this->facing->toFacing());
+ }
+
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ $hzFacing = HorizontalFacingOption::tryFromFacing($face);
+ if($hzFacing === null){
return false;
}
- $this->facing = $face;
+ $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
}
diff --git a/src/block/WallCoralFan.php b/src/block/WallCoralFan.php
index f9dece1cd..b6bfac73f 100644
--- a/src/block/WallCoralFan.php
+++ b/src/block/WallCoralFan.php
@@ -23,29 +23,30 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
-use pocketmine\math\Axis;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-final class WallCoralFan extends BaseCoral{
+final class WallCoralFan extends BaseCoral implements HorizontalFacing{
use HorizontalFacingTrait;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
- $axis = Facing::axis($face);
- if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ $hzFacing = HorizontalFacingOption::tryFromFacing($face);
+ if($hzFacing === null || !$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
- $this->facing = $face;
+ $this->facing = $hzFacing;
$this->dead = !$this->isCoveredWithWater();
@@ -54,14 +55,14 @@ final class WallCoralFan extends BaseCoral{
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
- if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){
+ if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing->toFacing()))){
$world->useBreakOn($this->position);
}else{
parent::onNearbyBlockChange();
}
}
- private function canBeSupportedAt(Block $block, int $face) : bool{
+ private function canBeSupportedAt(Block $block, Facing $face) : bool{
return $block->getAdjacentSupportType($face)->hasCenterSupport();
}
diff --git a/src/block/WallHangingSign.php b/src/block/WallHangingSign.php
new file mode 100644
index 000000000..44cdba2eb
--- /dev/null
+++ b/src/block/WallHangingSign.php
@@ -0,0 +1,83 @@
+facing->toFacing(), clockwise: true);
+ }
+
+ public function onNearbyBlockChange() : void{
+ //NOOP - disable default self-destruct behaviour
+ }
+
+ protected function recalculateCollisionBoxes() : array{
+ //only the cross bar is collidable
+ return [AxisAlignedBB::one()->trimmedCopy(Facing::DOWN, 7 / 8)->squashedCopy(Facing::axis($this->facing->toFacing()), 3 / 4)];
+ }
+
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ if($player === null){
+ return false;
+ }
+ $attachFace = Facing::axis($face) === Axis::Y ? Facing::rotateY($player->getHorizontalFacing(), clockwise: true) : $face;
+
+ if($this->canBeSupportedAt($blockReplace->getSide($attachFace), $attachFace)){
+ $direction = $attachFace;
+ }elseif($this->canBeSupportedAt($blockReplace->getSide($opposite = Facing::opposite($attachFace)), $opposite)){
+ $direction = $opposite;
+ }else{
+ return false;
+ }
+
+ $facing = Facing::rotateY(Facing::opposite($direction), clockwise: true);
+ //the front should always face the player if possible
+ if($facing === $player->getHorizontalFacing()){
+ $facing = Facing::opposite($facing);
+ }
+ $this->facing = HorizontalFacingOption::fromFacing($facing);
+
+ return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
+ }
+
+ private function canBeSupportedAt(Block $block, Facing $face) : bool{
+ return
+ ($block instanceof WallHangingSign && Facing::axis(Facing::rotateY($block->getFacing()->toFacing(), clockwise: true)) === Facing::axis($face)) ||
+ $block->getSupportType(Facing::opposite($face)) === SupportType::FULL;
+ }
+}
diff --git a/src/block/WallSign.php b/src/block/WallSign.php
index 07826eae7..2df05f97f 100644
--- a/src/block/WallSign.php
+++ b/src/block/WallSign.php
@@ -23,26 +23,28 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\HorizontalFacing;
+use pocketmine\block\utils\HorizontalFacingOption;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\item\Item;
-use pocketmine\math\Axis;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
-final class WallSign extends BaseSign{
+final class WallSign extends BaseSign implements HorizontalFacing{
use HorizontalFacingTrait;
- protected function getSupportingFace() : int{
- return Facing::opposite($this->facing);
+ protected function getSupportingFace() : Facing{
+ return Facing::opposite($this->facing->toFacing());
}
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
- if(Facing::axis($face) === Axis::Y){
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ $hzFacing = HorizontalFacingOption::tryFromFacing($face);
+ if($hzFacing === null){
return false;
}
- $this->facing = $face;
+ $this->facing = $hzFacing;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
}
diff --git a/src/block/WaterCauldron.php b/src/block/WaterCauldron.php
index 8129f2960..60bdc132e 100644
--- a/src/block/WaterCauldron.php
+++ b/src/block/WaterCauldron.php
@@ -37,6 +37,7 @@ use pocketmine\item\Potion;
use pocketmine\item\PotionType;
use pocketmine\item\SplashPotion;
use pocketmine\item\VanillaItems;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\CauldronAddDyeSound;
@@ -108,7 +109,7 @@ final class WaterCauldron extends FillableCauldron{
return new CauldronEmptyWaterSound();
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$world = $this->position->getWorld();
if(($dyeColor = match($item->getTypeId()){
ItemTypeIds::LAPIS_LAZULI => DyeColor::BLUE,
diff --git a/src/block/WaterLily.php b/src/block/WaterLily.php
index b04b1baed..d71a9d85b 100644
--- a/src/block/WaterLily.php
+++ b/src/block/WaterLily.php
@@ -34,10 +34,10 @@ class WaterLily extends Flowable{
}
protected function recalculateCollisionBoxes() : array{
- return [AxisAlignedBB::one()->contract(1 / 16, 0, 1 / 16)->trim(Facing::UP, 63 / 64)];
+ return [AxisAlignedBB::one()->contractedCopy(1 / 16, 0, 1 / 16)->trimmedCopy(Facing::UP, 63 / 64)];
}
- public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
+ public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, Facing $face, bool $isClickedBlock) : bool{
return !$blockReplace instanceof Water && $this->supportedWhenPlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
diff --git a/src/block/WeightedPressurePlate.php b/src/block/WeightedPressurePlate.php
index 726b31f6b..065f8b2c8 100644
--- a/src/block/WeightedPressurePlate.php
+++ b/src/block/WeightedPressurePlate.php
@@ -23,13 +23,14 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\AnalogRedstoneSignalEmitter;
use pocketmine\block\utils\AnalogRedstoneSignalEmitterTrait;
use function ceil;
use function count;
use function max;
use function min;
-class WeightedPressurePlate extends PressurePlate{
+class WeightedPressurePlate extends PressurePlate implements AnalogRedstoneSignalEmitter{
use AnalogRedstoneSignalEmitterTrait;
private readonly float $signalStrengthFactor;
diff --git a/src/block/Wood.php b/src/block/Wood.php
index 127533b98..6dc27efbe 100644
--- a/src/block/Wood.php
+++ b/src/block/Wood.php
@@ -23,16 +23,19 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\PillarRotation;
use pocketmine\block\utils\PillarRotationTrait;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodTypeTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Axe;
use pocketmine\item\Item;
+use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\ItemUseOnBlockSound;
-class Wood extends Opaque{
+class Wood extends Opaque implements PillarRotation, WoodMaterial{
use PillarRotationTrait;
use WoodTypeTrait;
@@ -62,7 +65,7 @@ class Wood extends Opaque{
return $this->woodType->isFlammable() ? 5 : 0;
}
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if(!$this->stripped && $item instanceof Axe){
$item->applyDamage(1);
$this->stripped = true;
diff --git a/src/block/WoodenButton.php b/src/block/WoodenButton.php
index 7ba8a7af0..4eed3a50e 100644
--- a/src/block/WoodenButton.php
+++ b/src/block/WoodenButton.php
@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodTypeTrait;
-class WoodenButton extends Button{
+class WoodenButton extends Button implements WoodMaterial{
use WoodTypeTrait;
protected function getActivationTime() : int{
diff --git a/src/block/WoodenDoor.php b/src/block/WoodenDoor.php
index 96f349e49..b7918a820 100644
--- a/src/block/WoodenDoor.php
+++ b/src/block/WoodenDoor.php
@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodTypeTrait;
-class WoodenDoor extends Door{
+class WoodenDoor extends Door implements WoodMaterial{
use WoodTypeTrait;
public function getFuelTime() : int{
diff --git a/src/block/WoodenFence.php b/src/block/WoodenFence.php
index c12043a86..73c8da44d 100644
--- a/src/block/WoodenFence.php
+++ b/src/block/WoodenFence.php
@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodTypeTrait;
-class WoodenFence extends Fence{
+class WoodenFence extends Fence implements WoodMaterial{
use WoodTypeTrait;
public function getFuelTime() : int{
diff --git a/src/block/WoodenPressurePlate.php b/src/block/WoodenPressurePlate.php
index a629c2f1c..6d638788b 100644
--- a/src/block/WoodenPressurePlate.php
+++ b/src/block/WoodenPressurePlate.php
@@ -23,10 +23,11 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodType;
use pocketmine\block\utils\WoodTypeTrait;
-class WoodenPressurePlate extends SimplePressurePlate{
+class WoodenPressurePlate extends SimplePressurePlate implements WoodMaterial{
use WoodTypeTrait;
public function __construct(
diff --git a/src/block/WoodenSlab.php b/src/block/WoodenSlab.php
index b388a36ea..3ed606c64 100644
--- a/src/block/WoodenSlab.php
+++ b/src/block/WoodenSlab.php
@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodTypeTrait;
-class WoodenSlab extends Slab{
+class WoodenSlab extends Slab implements WoodMaterial{
use WoodTypeTrait;
public function getFuelTime() : int{
diff --git a/src/block/WoodenStairs.php b/src/block/WoodenStairs.php
index 0d9ba62ce..8da3fceb6 100644
--- a/src/block/WoodenStairs.php
+++ b/src/block/WoodenStairs.php
@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodTypeTrait;
-class WoodenStairs extends Stair{
+class WoodenStairs extends Stair implements WoodMaterial{
use WoodTypeTrait;
public function getFuelTime() : int{
diff --git a/src/block/WoodenTrapdoor.php b/src/block/WoodenTrapdoor.php
index c0a6623a1..2b796df52 100644
--- a/src/block/WoodenTrapdoor.php
+++ b/src/block/WoodenTrapdoor.php
@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\WoodMaterial;
use pocketmine\block\utils\WoodTypeTrait;
-class WoodenTrapdoor extends Trapdoor{
+class WoodenTrapdoor extends Trapdoor implements WoodMaterial{
use WoodTypeTrait;
public function getFuelTime() : int{
diff --git a/src/block/Wool.php b/src/block/Wool.php
index 0b008ac04..d47c27d27 100644
--- a/src/block/Wool.php
+++ b/src/block/Wool.php
@@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
+use pocketmine\block\utils\Colored;
use pocketmine\block\utils\ColoredTrait;
-class Wool extends Opaque{
+class Wool extends Opaque implements Colored{
use ColoredTrait;
public function getFlameEncouragement() : int{
diff --git a/src/block/tile/Banner.php b/src/block/tile/Banner.php
index 08a560707..97ffe630d 100644
--- a/src/block/tile/Banner.php
+++ b/src/block/tile/Banner.php
@@ -41,6 +41,10 @@ class Banner extends Spawnable{
public const TAG_PATTERNS = "Patterns";
public const TAG_PATTERN_COLOR = "Color";
public const TAG_PATTERN_NAME = "Pattern";
+ public const TAG_TYPE = "Type";
+
+ public const TYPE_NORMAL = 0;
+ public const TYPE_OMINOUS = 1;
private DyeColor $baseColor = DyeColor::BLACK;
@@ -50,6 +54,8 @@ class Banner extends Spawnable{
*/
private array $patterns = [];
+ private int $type = self::TYPE_NORMAL;
+
public function readSaveData(CompoundTag $nbt) : void{
$colorIdMap = DyeColorIdMap::getInstance();
if(
@@ -75,6 +81,8 @@ class Banner extends Spawnable{
$this->patterns[] = new BannerPatternLayer($patternType, $patternColor);
}
}
+
+ $this->type = $nbt->getInt(self::TAG_TYPE);
}
protected function writeSaveData(CompoundTag $nbt) : void{
@@ -89,6 +97,7 @@ class Banner extends Spawnable{
);
}
$nbt->setTag(self::TAG_PATTERNS, $patterns);
+ $nbt->setInt(self::TAG_TYPE, $this->type);
}
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
@@ -103,6 +112,7 @@ class Banner extends Spawnable{
);
}
$nbt->setTag(self::TAG_PATTERNS, $patterns);
+ $nbt->setInt(self::TAG_TYPE, $this->type);
}
/**
@@ -136,6 +146,10 @@ class Banner extends Spawnable{
$this->patterns = $patterns;
}
+ public function getType() : int{ return $this->type; }
+
+ public function setType(int $type) : void{ $this->type = $type; }
+
public function getDefaultName() : string{
return "Banner";
}
diff --git a/src/block/tile/Bell.php b/src/block/tile/Bell.php
index 7a1e784e3..370964e9e 100644
--- a/src/block/tile/Bell.php
+++ b/src/block/tile/Bell.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block\tile;
+use pocketmine\data\SavedDataLoadingException;
use pocketmine\math\Facing;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
@@ -36,16 +37,16 @@ final class Bell extends Spawnable{
public const TAG_TICKS = "Ticks"; //TAG_Int
private bool $ringing = false;
- private int $facing = Facing::NORTH;
+ private Facing $facing = Facing::NORTH;
private int $ticks = 0;
public function isRinging() : bool{ return $this->ringing; }
public function setRinging(bool $ringing) : void{ $this->ringing = $ringing; }
- public function getFacing() : int{ return $this->facing; }
+ public function getFacing() : Facing{ return $this->facing; }
- public function setFacing(int $facing) : void{ $this->facing = $facing; }
+ public function setFacing(Facing $facing) : void{ $this->facing = $facing; }
public function getTicks() : int{ return $this->ticks; }
@@ -53,19 +54,22 @@ final class Bell extends Spawnable{
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setByte(self::TAG_RINGING, $this->ringing ? 1 : 0);
- $nbt->setInt(self::TAG_DIRECTION, $this->facing);
+ //TODO: suspicious use of internal Facing value for network
+ $nbt->setInt(self::TAG_DIRECTION, $this->facing->value);
$nbt->setInt(self::TAG_TICKS, $this->ticks);
}
public function readSaveData(CompoundTag $nbt) : void{
$this->ringing = $nbt->getByte(self::TAG_RINGING, 0) !== 0;
- $this->facing = $nbt->getInt(self::TAG_DIRECTION, Facing::NORTH);
+ //TODO: suspicious use of internal Facing value for storage
+ $this->facing = Facing::tryFrom($nbt->getInt(self::TAG_DIRECTION, Facing::NORTH->value)) ?? throw new SavedDataLoadingException("Invalid facing value");
$this->ticks = $nbt->getInt(self::TAG_TICKS, 0);
}
protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setByte(self::TAG_RINGING, $this->ringing ? 1 : 0);
- $nbt->setInt(self::TAG_DIRECTION, $this->facing);
+ //TODO: suspicious use of internal Facing value for storage
+ $nbt->setInt(self::TAG_DIRECTION, $this->facing->value);
$nbt->setInt(self::TAG_TICKS, $this->ticks);
}
@@ -77,7 +81,7 @@ final class Bell extends Spawnable{
* simpler as a BlockEventPacket. It's simpler to implement bells with this hack than to follow Mojang's complicated
* mess.
*/
- public function createFakeUpdatePacket(int $bellHitFace) : BlockActorDataPacket{
+ public function createFakeUpdatePacket(Facing $bellHitFace) : BlockActorDataPacket{
$nbt = $this->getSpawnCompound();
$nbt->setByte(self::TAG_RINGING, 1);
$nbt->setInt(self::TAG_DIRECTION, match($bellHitFace){
diff --git a/src/event/server/ServerEvent.php b/src/block/tile/HangingSign.php
similarity index 80%
rename from src/event/server/ServerEvent.php
rename to src/block/tile/HangingSign.php
index 97e79279d..a5be9ba5c 100644
--- a/src/event/server/ServerEvent.php
+++ b/src/block/tile/HangingSign.php
@@ -21,13 +21,11 @@
declare(strict_types=1);
+namespace pocketmine\block\tile;
+
/**
- * Events related to the server core, like networking, stop, console commands
+ * @deprecated
*/
-namespace pocketmine\event\server;
-
-use pocketmine\event\Event;
-
-abstract class ServerEvent extends Event{
+final class HangingSign extends Sign{
}
diff --git a/src/block/tile/ShulkerBox.php b/src/block/tile/ShulkerBox.php
index 13ed3980f..858bf4477 100644
--- a/src/block/tile/ShulkerBox.php
+++ b/src/block/tile/ShulkerBox.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block\tile;
use pocketmine\block\BlockTypeIds;
+use pocketmine\data\SavedDataLoadingException;
use pocketmine\inventory\Inventory;
use pocketmine\inventory\SimpleInventory;
use pocketmine\inventory\transaction\action\validator\CallbackSlotValidator;
@@ -43,7 +44,7 @@ class ShulkerBox extends Spawnable implements ContainerTile, Nameable{
public const TAG_FACING = "facing";
- protected int $facing = Facing::NORTH;
+ protected Facing $facing = Facing::NORTH;
protected Inventory $inventory;
@@ -64,13 +65,15 @@ class ShulkerBox extends Spawnable implements ContainerTile, Nameable{
public function readSaveData(CompoundTag $nbt) : void{
$this->loadName($nbt);
$this->loadItems($nbt);
- $this->facing = $nbt->getByte(self::TAG_FACING, $this->facing);
+ //TODO: suspicious use of internal Facing value for storage
+ $this->facing = Facing::tryFrom($nbt->getByte(self::TAG_FACING, $this->facing->value)) ?? throw new SavedDataLoadingException("Invalid facing value");
}
protected function writeSaveData(CompoundTag $nbt) : void{
$this->saveName($nbt);
$this->saveItems($nbt);
- $nbt->setByte(self::TAG_FACING, $this->facing);
+ //TODO: suspicious use of internal Facing value for storage
+ $nbt->setByte(self::TAG_FACING, $this->facing->value);
}
public function copyDataFromItem(Item $item) : void{
@@ -99,11 +102,11 @@ class ShulkerBox extends Spawnable implements ContainerTile, Nameable{
return $nbt;
}
- public function getFacing() : int{
+ public function getFacing() : Facing{
return $this->facing;
}
- public function setFacing(int $facing) : void{
+ public function setFacing(Facing $facing) : void{
$this->facing = $facing;
}
@@ -120,7 +123,8 @@ class ShulkerBox extends Spawnable implements ContainerTile, Nameable{
}
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
- $nbt->setByte(self::TAG_FACING, $this->facing);
+ //TODO: suspicious use of internal Facing value for network
+ $nbt->setByte(self::TAG_FACING, $this->facing->value);
$this->addNameSpawnData($nbt);
}
}
diff --git a/src/block/tile/Sign.php b/src/block/tile/Sign.php
index 0bb21a6d3..3e68317ba 100644
--- a/src/block/tile/Sign.php
+++ b/src/block/tile/Sign.php
@@ -32,11 +32,9 @@ use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\utils\Binary;
use pocketmine\world\World;
-use function array_pad;
-use function array_slice;
-use function explode;
use function implode;
use function mb_scrub;
+use function rtrim;
use function sprintf;
/**
@@ -60,14 +58,6 @@ class Sign extends Spawnable{
public const TAG_WAXED = "IsWaxed"; //TAG_Byte
public const TAG_LOCKED_FOR_EDITING_BY = "LockedForEditingBy"; //TAG_Long
- /**
- * @return string[]
- * @deprecated
- */
- public static function fixTextBlob(string $blob) : array{
- return array_slice(array_pad(explode("\n", $blob, limit: 5), 4, ""), 0, 4);
- }
-
protected SignText $text;
private bool $waxed = false;
@@ -117,7 +107,7 @@ class Sign extends Spawnable{
protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setTag(self::TAG_FRONT_TEXT, CompoundTag::create()
- ->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()))
+ ->setString(self::TAG_TEXT_BLOB, rtrim(implode("\n", $this->text->getLines()), "\n"))
->setInt(self::TAG_TEXT_COLOR, Binary::signInt($this->text->getBaseColor()->toARGB()))
->setByte(self::TAG_GLOWING_TEXT, $this->text->isGlowing() ? 1 : 0)
->setByte(self::TAG_PERSIST_FORMATTING, 1)
@@ -162,7 +152,7 @@ class Sign extends Spawnable{
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setTag(self::TAG_FRONT_TEXT, CompoundTag::create()
- ->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()))
+ ->setString(self::TAG_TEXT_BLOB, rtrim(implode("\n", $this->text->getLines()), "\n"))
->setInt(self::TAG_TEXT_COLOR, Binary::signInt($this->text->getBaseColor()->toARGB()))
->setByte(self::TAG_GLOWING_TEXT, $this->text->isGlowing() ? 1 : 0)
->setByte(self::TAG_PERSIST_FORMATTING, 1) //TODO: not sure what this is used for
diff --git a/src/block/tile/Spawnable.php b/src/block/tile/Spawnable.php
index 956652eac..d801e5324 100644
--- a/src/block/tile/Spawnable.php
+++ b/src/block/tile/Spawnable.php
@@ -32,7 +32,7 @@ use pocketmine\network\mcpe\protocol\types\CacheableNbt;
use function get_class;
abstract class Spawnable extends Tile{
- /** @phpstan-var CacheableNbt<\pocketmine\nbt\tag\CompoundTag>|null */
+ /** @phpstan-var CacheableNbt|null */
private ?CacheableNbt $spawnCompoundCache = null;
public function clearSpawnCompoundCache() : void{
@@ -59,7 +59,7 @@ abstract class Spawnable extends Tile{
* Returns encoded NBT (varint, little-endian) used to spawn this tile to clients. Uses cache where possible,
* populates cache if it is null.
*
- * @phpstan-return CacheableNbt<\pocketmine\nbt\tag\CompoundTag>
+ * @phpstan-return CacheableNbt
*/
final public function getSerializedSpawnCompound() : CacheableNbt{
if($this->spawnCompoundCache === null){
diff --git a/src/block/tile/TileFactory.php b/src/block/tile/TileFactory.php
index 26e0af6a5..108483894 100644
--- a/src/block/tile/TileFactory.php
+++ b/src/block/tile/TileFactory.php
@@ -79,6 +79,7 @@ final class TileFactory{
$this->register(SporeBlossom::class, ["SporeBlossom", "minecraft:spore_blossom"]);
$this->register(MobHead::class, ["Skull", "minecraft:skull"]);
$this->register(GlowingItemFrame::class, ["GlowItemFrame"]);
+ $this->register(HangingSign::class, ["HangingSign", "minecraft:hanging_sign"]);
//TODO: ChalkboardBlock
//TODO: ChemistryTable
diff --git a/src/block/utils/Ageable.php b/src/block/utils/Ageable.php
new file mode 100644
index 000000000..180392ef3
--- /dev/null
+++ b/src/block/utils/Ageable.php
@@ -0,0 +1,37 @@
+age; }
+ public function getMaxAge() : int{ return self::MAX_AGE; }
+
/**
* @return $this
*/
diff --git a/src/block/utils/AnalogRedstoneSignalEmitter.php b/src/block/utils/AnalogRedstoneSignalEmitter.php
new file mode 100644
index 000000000..fa2cc4b11
--- /dev/null
+++ b/src/block/utils/AnalogRedstoneSignalEmitter.php
@@ -0,0 +1,34 @@
+facing($this->facing);
+ $w->enum($this->facing);
}
- public function getFacing() : int{ return $this->facing; }
+ public function getFacing() : Facing{ return $this->facing; }
/** @return $this */
- public function setFacing(int $facing) : self{
- Facing::validate($this->facing);
+ public function setFacing(Facing $facing) : self{
$this->facing = $facing;
return $this;
}
diff --git a/src/block/utils/CandleTrait.php b/src/block/utils/CandleTrait.php
index 0cbd13044..3f8e164bf 100644
--- a/src/block/utils/CandleTrait.php
+++ b/src/block/utils/CandleTrait.php
@@ -29,6 +29,7 @@ use pocketmine\item\Durable;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds;
+use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
@@ -45,9 +46,10 @@ trait CandleTrait{
/**
* @param Item[] &$returnedItems
+ *
* @see Block::onInteract()
*/
- public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
+ public function onInteract(Item $item, Facing $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item->getTypeId() === ItemTypeIds::FIRE_CHARGE || $item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
if($this->lit){
return true;
diff --git a/src/block/utils/Colored.php b/src/block/utils/Colored.php
new file mode 100644
index 000000000..af26d0b5d
--- /dev/null
+++ b/src/block/utils/Colored.php
@@ -0,0 +1,34 @@
+waxed && $item->getTypeId() === ItemTypeIds::HONEYCOMB){
$this->waxed = true;
$this->position->getWorld()->setBlock($this->position, $this);
diff --git a/src/block/utils/CoralMaterial.php b/src/block/utils/CoralMaterial.php
new file mode 100644
index 000000000..0284322ac
--- /dev/null
+++ b/src/block/utils/CoralMaterial.php
@@ -0,0 +1,41 @@
+facing = Facing::opposite($player->getHorizontalFacing());
+ $this->facing = HorizontalFacingOption::fromFacing(Facing::opposite($player->getHorizontalFacing()));
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
diff --git a/src/block/utils/HorizontalFacing.php b/src/block/utils/HorizontalFacing.php
new file mode 100644
index 000000000..a4c1fed1d
--- /dev/null
+++ b/src/block/utils/HorizontalFacing.php
@@ -0,0 +1,31 @@
+value;
+ case SOUTH = Facing::SOUTH->value;
+ case WEST = Facing::WEST->value;
+ case EAST = Facing::EAST->value;
+
+ public static function tryFromFacing(Facing $facing) : ?self{
+ return match($facing){
+ Facing::NORTH => self::NORTH,
+ Facing::SOUTH => self::SOUTH,
+ Facing::WEST => self::WEST,
+ Facing::EAST => self::EAST,
+ default => null,
+ };
+ }
+
+ public static function fromFacing(Facing $facing) : self{
+ return self::tryFromFacing($facing) ?? throw new \InvalidArgumentException("Facing $facing->name cannot be converted to a horizontal facing");
+ }
+
+ public function toFacing() : Facing{
+ return match($this){
+ self::NORTH => Facing::NORTH,
+ self::SOUTH => Facing::SOUTH,
+ self::WEST => Facing::WEST,
+ self::EAST => Facing::EAST,
+ };
+ }
+}
diff --git a/src/block/utils/HorizontalFacingTrait.php b/src/block/utils/HorizontalFacingTrait.php
index a5bd6dcf4..fb950b4f2 100644
--- a/src/block/utils/HorizontalFacingTrait.php
+++ b/src/block/utils/HorizontalFacingTrait.php
@@ -24,24 +24,18 @@ declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\data\runtime\RuntimeDataDescriber;
-use pocketmine\math\Axis;
-use pocketmine\math\Facing;
trait HorizontalFacingTrait{
- protected int $facing = Facing::NORTH;
+ protected HorizontalFacingOption $facing = HorizontalFacingOption::NORTH;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
- $w->horizontalFacing($this->facing);
+ $w->enum($this->facing);
}
- public function getFacing() : int{ return $this->facing; }
+ public function getFacing() : HorizontalFacingOption{ return $this->facing; }
/** @return $this */
- public function setFacing(int $facing) : self{
- $axis = Facing::axis($facing);
- if($axis !== Axis::X && $axis !== Axis::Z){
- throw new \InvalidArgumentException("Facing must be horizontal");
- }
+ public function setFacing(HorizontalFacingOption $facing) : self{
$this->facing = $facing;
return $this;
}
diff --git a/src/block/utils/LeverFacing.php b/src/block/utils/LeverFacing.php
index 6edb29376..73728d08f 100644
--- a/src/block/utils/LeverFacing.php
+++ b/src/block/utils/LeverFacing.php
@@ -35,7 +35,7 @@ enum LeverFacing{
case SOUTH;
case WEST;
- public function getFacing() : int{
+ public function getFacing() : Facing{
return match($this){
self::UP_AXIS_X, self::UP_AXIS_Z => Facing::UP,
self::DOWN_AXIS_X, self::DOWN_AXIS_Z => Facing::DOWN,
diff --git a/src/block/utils/Lightable.php b/src/block/utils/Lightable.php
new file mode 100644
index 000000000..36ac479f3
--- /dev/null
+++ b/src/block/utils/Lightable.php
@@ -0,0 +1,34 @@
+value];
$x = $blockX + $dx;
$y = $blockY + $dy;
$z = $blockZ + $dz;
@@ -99,10 +100,10 @@ final class MinimumCostFlowCalculator{
* @return int[]
*/
public function getOptimalFlowDirections(int $originX, int $originY, int $originZ) : array{
- $flowCost = array_fill_keys(Facing::HORIZONTAL, 1000);
+ $flowCost = array_fill_keys(array_map(fn(Facing $f) => $f->value, Facing::HORIZONTAL), 1000);
$maxCost = intdiv(4, $this->flowDecayPerBlock);
foreach(Facing::HORIZONTAL as $j){
- [$dx, $dy, $dz] = Facing::OFFSET[$j];
+ [$dx, $dy, $dz] = Facing::OFFSET[$j->value];
$x = $originX + $dx;
$y = $originY + $dy;
$z = $originZ + $dz;
@@ -111,12 +112,12 @@ final class MinimumCostFlowCalculator{
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::BLOCKED;
}elseif($this->world->getBlockAt($x, $y - 1, $z)->canBeFlowedInto()){
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::CAN_FLOW_DOWN;
- $flowCost[$j] = $maxCost = 0;
+ $flowCost[$j->value] = $maxCost = 0;
}elseif($maxCost > 0){
$this->flowCostVisited[World::blockHash($x, $y, $z)] = self::CAN_FLOW;
$opposite = Facing::opposite($j);
- $flowCost[$j] = $this->calculateFlowCost($x, $y, $z, 1, $maxCost, $opposite, $opposite);
- $maxCost = min($maxCost, $flowCost[$j]);
+ $flowCost[$j->value] = $this->calculateFlowCost($x, $y, $z, 1, $maxCost, $opposite, $opposite);
+ $maxCost = min($maxCost, $flowCost[$j->value]);
}
}
diff --git a/src/block/utils/MultiAnyFacing.php b/src/block/utils/MultiAnyFacing.php
new file mode 100644
index 000000000..c50e36ff0
--- /dev/null
+++ b/src/block/utils/MultiAnyFacing.php
@@ -0,0 +1,45 @@
+facingFlags($this->faces);
+ $w->enumSet($this->faces, Facing::cases());
}
- /** @return int[] */
+ /** @return Facing[] */
public function getFaces() : array{ return $this->faces; }
- public function hasFace(int $face) : bool{
- return isset($this->faces[$face]);
+ public function hasFace(Facing $face) : bool{
+ return isset($this->faces[spl_object_id($face)]);
}
/**
- * @param int[] $faces
+ * @param Facing[] $faces
* @return $this
*/
public function setFaces(array $faces) : self{
$uniqueFaces = [];
foreach($faces as $face){
- Facing::validate($face);
- $uniqueFaces[$face] = $face;
+ $uniqueFaces[spl_object_id($face)] = $face;
}
$this->faces = $uniqueFaces;
return $this;
}
/** @return $this */
- public function setFace(int $face, bool $value) : self{
- Facing::validate($face);
+ public function setFace(Facing $face, bool $value) : self{
if($value){
- $this->faces[$face] = $face;
+ $this->faces[spl_object_id($face)] = $face;
}else{
- unset($this->faces[$face]);
+ unset($this->faces[spl_object_id($face)]);
}
return $this;
}
diff --git a/src/block/utils/MultiAnySupportTrait.php b/src/block/utils/MultiAnySupportTrait.php
index ae1da7bef..55164b6f0 100644
--- a/src/block/utils/MultiAnySupportTrait.php
+++ b/src/block/utils/MultiAnySupportTrait.php
@@ -42,11 +42,11 @@ trait MultiAnySupportTrait{
/**
* Returns a list of faces that block should already have when placed.
*
- * @return int[]
+ * @return Facing[]
*/
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{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->faces = $this->getInitialPlaceFaces($blockReplace);
$availableFaces = $this->getAvailableFaces();
@@ -55,8 +55,8 @@ trait MultiAnySupportTrait{
}
$opposite = Facing::opposite($face);
- $placedFace = isset($availableFaces[$opposite]) ? $opposite : array_key_first($availableFaces);
- $this->faces[$placedFace] = $placedFace;
+ $placedFace = isset($availableFaces[$opposite->value]) ? $opposite : $availableFaces[array_key_first($availableFaces)];
+ $this->faces[$placedFace->value] = $placedFace;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@@ -66,7 +66,7 @@ trait MultiAnySupportTrait{
foreach($this->faces as $face){
if($this->getAdjacentSupportType($face) !== SupportType::FULL){
- unset($this->faces[$face]);
+ unset($this->faces[$face->value]);
$changed = true;
}
}
@@ -82,13 +82,14 @@ trait MultiAnySupportTrait{
}
/**
- * @return array $faces
+ * @return Facing[]
+ * @phpstan-return array
*/
private function getAvailableFaces() : array{
$faces = [];
foreach(Facing::ALL as $face){
if(!$this->hasFace($face) && $this->getAdjacentSupportType($face) === SupportType::FULL){
- $faces[$face] = $face;
+ $faces[$face->value] = $face;
}
}
return $faces;
diff --git a/src/block/utils/PillarRotation.php b/src/block/utils/PillarRotation.php
new file mode 100644
index 000000000..cfba744f1
--- /dev/null
+++ b/src/block/utils/PillarRotation.php
@@ -0,0 +1,34 @@
+axis($this->axis);
+ $w->enum($this->axis);
}
/** @see Axis */
- public function getAxis() : int{ return $this->axis; }
+ public function getAxis() : Axis{ return $this->axis; }
/** @return $this */
- public function setAxis(int $axis) : self{
+ public function setAxis(Axis $axis) : self{
$this->axis = $axis;
return $this;
}
@@ -51,7 +51,7 @@ trait PillarRotationTrait{
/**
* @see Block::place()
*/
- public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
+ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, Facing $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->axis = Facing::axis($face);
/** @see Block::place() */
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
diff --git a/src/block/utils/PoweredByRedstone.php b/src/block/utils/PoweredByRedstone.php
new file mode 100644
index 000000000..452de4309
--- /dev/null
+++ b/src/block/utils/PoweredByRedstone.php
@@ -0,0 +1,34 @@
+ [
- Facing::NORTH,
- Facing::SOUTH
+ Facing::NORTH->value,
+ Facing::SOUTH->value
],
BlockLegacyMetadata::RAIL_STRAIGHT_EAST_WEST => [
- Facing::EAST,
- Facing::WEST
+ Facing::EAST->value,
+ Facing::WEST->value
],
//ascending
BlockLegacyMetadata::RAIL_ASCENDING_EAST => [
- Facing::WEST,
- Facing::EAST | self::FLAG_ASCEND
+ Facing::WEST->value,
+ Facing::EAST->value | self::FLAG_ASCEND
],
BlockLegacyMetadata::RAIL_ASCENDING_WEST => [
- Facing::EAST,
- Facing::WEST | self::FLAG_ASCEND
+ Facing::EAST->value,
+ Facing::WEST->value | self::FLAG_ASCEND
],
BlockLegacyMetadata::RAIL_ASCENDING_NORTH => [
- Facing::SOUTH,
- Facing::NORTH | self::FLAG_ASCEND
+ Facing::SOUTH->value,
+ Facing::NORTH->value | self::FLAG_ASCEND
],
BlockLegacyMetadata::RAIL_ASCENDING_SOUTH => [
- Facing::NORTH,
- Facing::SOUTH | self::FLAG_ASCEND
+ Facing::NORTH->value,
+ Facing::SOUTH->value | self::FLAG_ASCEND
]
];
/* extended meta values for regular rails, to allow curving */
public const CURVE_CONNECTIONS = [
BlockLegacyMetadata::RAIL_CURVE_SOUTHEAST => [
- Facing::SOUTH,
- Facing::EAST
+ Facing::SOUTH->value,
+ Facing::EAST->value
],
BlockLegacyMetadata::RAIL_CURVE_SOUTHWEST => [
- Facing::SOUTH,
- Facing::WEST
+ Facing::SOUTH->value,
+ Facing::WEST->value
],
BlockLegacyMetadata::RAIL_CURVE_NORTHWEST => [
- Facing::NORTH,
- Facing::WEST
+ Facing::NORTH->value,
+ Facing::WEST->value
],
BlockLegacyMetadata::RAIL_CURVE_NORTHEAST => [
- Facing::NORTH,
- Facing::EAST
+ Facing::NORTH->value,
+ Facing::EAST->value
]
];
}
diff --git a/src/block/utils/RailShape.php b/src/block/utils/RailShape.php
new file mode 100644
index 000000000..dfd0d09a1
--- /dev/null
+++ b/src/block/utils/RailShape.php
@@ -0,0 +1,41 @@
+canBeSupportedAt($blockReplace) && parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
diff --git a/src/block/utils/StraightOnlyRailShape.php b/src/block/utils/StraightOnlyRailShape.php
new file mode 100644
index 000000000..36ce3a89f
--- /dev/null
+++ b/src/block/utils/StraightOnlyRailShape.php
@@ -0,0 +1,33 @@
+value;
+ case FLAT_AXIS_X = RailShape::FLAT_AXIS_X->value;
+ case ASCENDING_EAST = RailShape::ASCENDING_EAST->value;
+ case ASCENDING_WEST = RailShape::ASCENDING_WEST->value;
+ case ASCENDING_NORTH = RailShape::ASCENDING_NORTH->value;
+ case ASCENDING_SOUTH = RailShape::ASCENDING_SOUTH->value;
+}
diff --git a/src/block/utils/WoodMaterial.php b/src/block/utils/WoodMaterial.php
new file mode 100644
index 000000000..2fd2bbcca
--- /dev/null
+++ b/src/block/utils/WoodMaterial.php
@@ -0,0 +1,29 @@
+ */
public function getRecipeRegisteredCallbacks() : ObjectSet{ return $this->recipeRegisteredCallbacks; }
- /**
- * Function used to arrange Shapeless Recipe ingredient lists into a consistent order.
- * @deprecated
- */
- public static function sort(Item $i1, Item $i2) : int{
- //Use spaceship operator to compare each property, then try the next one if they are equivalent.
- ($retval = $i1->getStateId() <=> $i2->getStateId()) === 0 && ($retval = $i1->getCount() <=> $i2->getCount()) === 0;
-
- return $retval;
- }
-
private static function hashOutput(Item $output) : string{
$write = new BinaryStream();
$write->putVarInt($output->getStateId());
diff --git a/src/crafting/CraftingManagerFromDataHelper.php b/src/crafting/CraftingManagerFromDataHelper.php
index a43054e98..b02b965b7 100644
--- a/src/crafting/CraftingManagerFromDataHelper.php
+++ b/src/crafting/CraftingManagerFromDataHelper.php
@@ -162,7 +162,7 @@ final class CraftingManagerFromDataHelper{
}
$mapper = new \JsonMapper();
- $mapper->bStrictObjectTypeChecking = true;
+ $mapper->bStrictObjectTypeChecking = false; //to allow hydrating ItemStackData - since this is only used for offline data it's safe
$mapper->bExceptionOnUndefinedProperty = true;
$mapper->bExceptionOnMissingData = true;
diff --git a/src/crafting/json/ItemStackData.php b/src/crafting/json/ItemStackData.php
index 032c7da7d..bf079e920 100644
--- a/src/crafting/json/ItemStackData.php
+++ b/src/crafting/json/ItemStackData.php
@@ -23,7 +23,9 @@ declare(strict_types=1);
namespace pocketmine\crafting\json;
-final class ItemStackData{
+use function count;
+
+final class ItemStackData implements \JsonSerializable{
/** @required */
public string $name;
@@ -40,4 +42,15 @@ final class ItemStackData{
public function __construct(string $name){
$this->name = $name;
}
+
+ /**
+ * @return mixed[]|string
+ */
+ public function jsonSerialize() : array|string{
+ $result = (array) $this;
+ if(count($result) === 1 && isset($result["name"])){
+ return $this->name;
+ }
+ return $result;
+ }
}
diff --git a/src/crash/CrashDump.php b/src/crash/CrashDump.php
index 49a587c34..15c48c7a7 100644
--- a/src/crash/CrashDump.php
+++ b/src/crash/CrashDump.php
@@ -26,7 +26,6 @@ namespace pocketmine\crash;
use Composer\InstalledVersions;
use pocketmine\errorhandler\ErrorTypeToStringMap;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
-use pocketmine\plugin\PluginBase;
use pocketmine\plugin\PluginManager;
use pocketmine\Server;
use pocketmine\thread\ThreadCrashInfoFrame;
@@ -259,10 +258,8 @@ class CrashDump{
}
if(file_exists($filePath)){
- $reflection = new \ReflectionClass(PluginBase::class);
- $file = $reflection->getProperty("file");
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
- $filePath = Filesystem::cleanPath($file->getValue($plugin));
+ $filePath = Filesystem::cleanPath($plugin->getFile());
if(str_starts_with($frameCleanPath, $filePath)){
$this->data->plugin = $plugin->getName();
break;
diff --git a/src/data/bedrock/BedrockDataFiles.php b/src/data/bedrock/BedrockDataFiles.php
index 1ecb707cc..53bd9b11e 100644
--- a/src/data/bedrock/BedrockDataFiles.php
+++ b/src/data/bedrock/BedrockDataFiles.php
@@ -31,8 +31,7 @@ final class BedrockDataFiles{
}
public const BANNER_PATTERNS_JSON = BEDROCK_DATA_PATH . '/banner_patterns.json';
- public const BIOME_DEFINITIONS_NBT = BEDROCK_DATA_PATH . '/biome_definitions.nbt';
- public const BIOME_DEFINITIONS_FULL_NBT = BEDROCK_DATA_PATH . '/biome_definitions_full.nbt';
+ public const BIOME_DEFINITIONS_JSON = BEDROCK_DATA_PATH . '/biome_definitions.json';
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';
diff --git a/src/data/bedrock/MushroomBlockTypeIdMap.php b/src/data/bedrock/MushroomBlockTypeIdMap.php
deleted file mode 100644
index a25336d89..000000000
--- a/src/data/bedrock/MushroomBlockTypeIdMap.php
+++ /dev/null
@@ -1,52 +0,0 @@
- */
- use IntSaveIdMapTrait;
-
- public function __construct(){
- foreach(MushroomBlockType::cases() as $case){
- $this->register(match($case){
- MushroomBlockType::PORES => LegacyMeta::MUSHROOM_BLOCK_ALL_PORES,
- MushroomBlockType::CAP_NORTHWEST => LegacyMeta::MUSHROOM_BLOCK_CAP_NORTHWEST_CORNER,
- MushroomBlockType::CAP_NORTH => LegacyMeta::MUSHROOM_BLOCK_CAP_NORTH_SIDE,
- MushroomBlockType::CAP_NORTHEAST => LegacyMeta::MUSHROOM_BLOCK_CAP_NORTHEAST_CORNER,
- MushroomBlockType::CAP_WEST => LegacyMeta::MUSHROOM_BLOCK_CAP_WEST_SIDE,
- MushroomBlockType::CAP_MIDDLE => LegacyMeta::MUSHROOM_BLOCK_CAP_TOP_ONLY,
- MushroomBlockType::CAP_EAST => LegacyMeta::MUSHROOM_BLOCK_CAP_EAST_SIDE,
- MushroomBlockType::CAP_SOUTHWEST => LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHWEST_CORNER,
- MushroomBlockType::CAP_SOUTH => LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTH_SIDE,
- MushroomBlockType::CAP_SOUTHEAST => LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHEAST_CORNER,
- MushroomBlockType::ALL_CAP => LegacyMeta::MUSHROOM_BLOCK_ALL_CAP,
- }, $case);
- }
- }
-}
diff --git a/src/data/bedrock/WorldDataVersions.php b/src/data/bedrock/WorldDataVersions.php
new file mode 100644
index 000000000..e682eb43a
--- /dev/null
+++ b/src/data/bedrock/WorldDataVersions.php
@@ -0,0 +1,66 @@
+
+ * @var (\Closure|BlockStateData)[]
+ * @phpstan-var array
*/
private array $serializers = [];
@@ -204,20 +47,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
*/
private array $cache = [];
- public function __construct(){
- $this->registerCandleSerializers();
- $this->registerFlatColorBlockSerializers();
- $this->registerFlatCoralSerializers();
- $this->registerCauldronSerializers();
- $this->registerFlatWoodBlockSerializers();
- $this->registerLeavesSerializers();
- $this->registerSaplingSerializers();
- $this->registerMobHeadSerializers();
- $this->registerCopperSerializers();
- $this->registerSimpleSerializers();
- $this->registerSerializers();
- }
-
public function serialize(int $stateId) : BlockStateData{
//TODO: singleton usage not ideal
//TODO: we may want to deduplicate cache entries to avoid wasting memory
@@ -231,29 +60,14 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
/**
* @phpstan-template TBlockType of Block
* @phpstan-param TBlockType $block
- * @phpstan-param \Closure(TBlockType) : Writer $serializer
+ * @phpstan-param \Closure(TBlockType) : (Writer|BlockStateData)|Writer|BlockStateData $serializer
*/
- public function map(Block $block, \Closure $serializer) : void{
+ public function map(Block $block, \Closure|Writer|BlockStateData $serializer) : void{
if(isset($this->serializers[$block->getTypeId()])){
- throw new \InvalidArgumentException("Block type ID " . $block->getTypeId() . " already has a serializer registered");
+ throw new \InvalidArgumentException("Block type ID " . $block->getTypeId() . " (" . $block->getName() . ") already has a serializer registered");
}
- $this->serializers[$block->getTypeId()] = $serializer;
- }
-
- public function mapSimple(Block $block, string $id) : void{
- $this->map($block, fn() => Writer::create($id));
- }
-
- public function mapSlab(Slab $block, string $singleId, string $doubleId) : void{
- $this->map($block, fn(Slab $block) => Helper::encodeSlab($block, $singleId, $doubleId));
- }
-
- public function mapStairs(Stair $block, string $id) : void{
- $this->map($block, fn(Stair $block) => Helper::encodeStairs($block, Writer::create($id)));
- }
-
- public function mapLog(Wood $block, string $unstrippedId, string $strippedId) : void{
- $this->map($block, fn(Wood $block) => Helper::encodeLog($block, $unstrippedId, $strippedId));
+ //writer accepted for convenience only
+ $this->serializers[$block->getTypeId()] = $serializer instanceof Writer ? $serializer->getBlockStateData() : $serializer;
}
/**
@@ -270,1616 +84,20 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
throw new BlockStateSerializeException("No serializer registered for " . get_class($blockState) . " with type ID $typeId");
}
+ if($locatedSerializer instanceof BlockStateData){ //static data, not dependent on state
+ return $locatedSerializer;
+ }
+
/**
* TODO: there is no guarantee that this type actually matches that of $blockState - a plugin may have stolen
* the type ID of the block (which never makes sense, even in a world where overriding block types is a thing).
* In the future we'll need some way to guarantee that type IDs are never reused (perhaps spl_object_id()?)
*
- * @var \Closure $serializer
- * @phpstan-var \Closure(TBlockType) : Writer $serializer
+ * @var \Closure $locatedSerializer
+ * @phpstan-var \Closure(TBlockType) : (Writer|BlockStateData) $locatedSerializer
*/
- $serializer = $locatedSerializer;
+ $result = $locatedSerializer($blockState);
- /** @var Writer $writer */
- $writer = $serializer($blockState);
- return $writer->getBlockStateData();
- }
-
- private function registerCandleSerializers() : void{
- $this->map(Blocks::CANDLE(), fn(Candle $block) => Helper::encodeCandle($block, new Writer(Ids::CANDLE)));
- $this->map(Blocks::DYED_CANDLE(), fn(DyedCandle $block) => Helper::encodeCandle($block, new Writer(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_CANDLE,
- DyeColor::BLUE => Ids::BLUE_CANDLE,
- DyeColor::BROWN => Ids::BROWN_CANDLE,
- DyeColor::CYAN => Ids::CYAN_CANDLE,
- DyeColor::GRAY => Ids::GRAY_CANDLE,
- DyeColor::GREEN => Ids::GREEN_CANDLE,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_CANDLE,
- DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_CANDLE,
- DyeColor::LIME => Ids::LIME_CANDLE,
- DyeColor::MAGENTA => Ids::MAGENTA_CANDLE,
- DyeColor::ORANGE => Ids::ORANGE_CANDLE,
- DyeColor::PINK => Ids::PINK_CANDLE,
- DyeColor::PURPLE => Ids::PURPLE_CANDLE,
- DyeColor::RED => Ids::RED_CANDLE,
- DyeColor::WHITE => Ids::WHITE_CANDLE,
- DyeColor::YELLOW => Ids::YELLOW_CANDLE,
- })));
- $this->map(Blocks::CAKE_WITH_CANDLE(), fn(CakeWithCandle $block) => Writer::create(Ids::CANDLE_CAKE)
- ->writeBool(StateNames::LIT, $block->isLit()));
- $this->map(Blocks::CAKE_WITH_DYED_CANDLE(), fn(CakeWithDyedCandle $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_CANDLE_CAKE,
- DyeColor::BLUE => Ids::BLUE_CANDLE_CAKE,
- DyeColor::BROWN => Ids::BROWN_CANDLE_CAKE,
- DyeColor::CYAN => Ids::CYAN_CANDLE_CAKE,
- DyeColor::GRAY => Ids::GRAY_CANDLE_CAKE,
- DyeColor::GREEN => Ids::GREEN_CANDLE_CAKE,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_CANDLE_CAKE,
- DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_CANDLE_CAKE,
- DyeColor::LIME => Ids::LIME_CANDLE_CAKE,
- DyeColor::MAGENTA => Ids::MAGENTA_CANDLE_CAKE,
- DyeColor::ORANGE => Ids::ORANGE_CANDLE_CAKE,
- DyeColor::PINK => Ids::PINK_CANDLE_CAKE,
- DyeColor::PURPLE => Ids::PURPLE_CANDLE_CAKE,
- DyeColor::RED => Ids::RED_CANDLE_CAKE,
- DyeColor::WHITE => Ids::WHITE_CANDLE_CAKE,
- DyeColor::YELLOW => Ids::YELLOW_CANDLE_CAKE,
- })->writeBool(StateNames::LIT, $block->isLit()));
- }
-
- public function registerFlatColorBlockSerializers() : void{
- $this->map(Blocks::STAINED_HARDENED_GLASS(), fn(StainedHardenedGlass $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::HARD_BLACK_STAINED_GLASS,
- DyeColor::BLUE => Ids::HARD_BLUE_STAINED_GLASS,
- DyeColor::BROWN => Ids::HARD_BROWN_STAINED_GLASS,
- DyeColor::CYAN => Ids::HARD_CYAN_STAINED_GLASS,
- DyeColor::GRAY => Ids::HARD_GRAY_STAINED_GLASS,
- DyeColor::GREEN => Ids::HARD_GREEN_STAINED_GLASS,
- DyeColor::LIGHT_BLUE => Ids::HARD_LIGHT_BLUE_STAINED_GLASS,
- DyeColor::LIGHT_GRAY => Ids::HARD_LIGHT_GRAY_STAINED_GLASS,
- DyeColor::LIME => Ids::HARD_LIME_STAINED_GLASS,
- DyeColor::MAGENTA => Ids::HARD_MAGENTA_STAINED_GLASS,
- DyeColor::ORANGE => Ids::HARD_ORANGE_STAINED_GLASS,
- DyeColor::PINK => Ids::HARD_PINK_STAINED_GLASS,
- DyeColor::PURPLE => Ids::HARD_PURPLE_STAINED_GLASS,
- DyeColor::RED => Ids::HARD_RED_STAINED_GLASS,
- DyeColor::WHITE => Ids::HARD_WHITE_STAINED_GLASS,
- DyeColor::YELLOW => Ids::HARD_YELLOW_STAINED_GLASS,
- }));
-
- $this->map(Blocks::STAINED_HARDENED_GLASS_PANE(), fn(StainedHardenedGlassPane $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::HARD_BLACK_STAINED_GLASS_PANE,
- DyeColor::BLUE => Ids::HARD_BLUE_STAINED_GLASS_PANE,
- DyeColor::BROWN => Ids::HARD_BROWN_STAINED_GLASS_PANE,
- DyeColor::CYAN => Ids::HARD_CYAN_STAINED_GLASS_PANE,
- DyeColor::GRAY => Ids::HARD_GRAY_STAINED_GLASS_PANE,
- DyeColor::GREEN => Ids::HARD_GREEN_STAINED_GLASS_PANE,
- DyeColor::LIGHT_BLUE => Ids::HARD_LIGHT_BLUE_STAINED_GLASS_PANE,
- DyeColor::LIGHT_GRAY => Ids::HARD_LIGHT_GRAY_STAINED_GLASS_PANE,
- DyeColor::LIME => Ids::HARD_LIME_STAINED_GLASS_PANE,
- DyeColor::MAGENTA => Ids::HARD_MAGENTA_STAINED_GLASS_PANE,
- DyeColor::ORANGE => Ids::HARD_ORANGE_STAINED_GLASS_PANE,
- DyeColor::PINK => Ids::HARD_PINK_STAINED_GLASS_PANE,
- DyeColor::PURPLE => Ids::HARD_PURPLE_STAINED_GLASS_PANE,
- DyeColor::RED => Ids::HARD_RED_STAINED_GLASS_PANE,
- DyeColor::WHITE => Ids::HARD_WHITE_STAINED_GLASS_PANE,
- DyeColor::YELLOW => Ids::HARD_YELLOW_STAINED_GLASS_PANE,
- }));
-
- $this->map(Blocks::GLAZED_TERRACOTTA(), function(GlazedTerracotta $block) : Writer{
- return Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_GLAZED_TERRACOTTA,
- DyeColor::BLUE => Ids::BLUE_GLAZED_TERRACOTTA,
- DyeColor::BROWN => Ids::BROWN_GLAZED_TERRACOTTA,
- DyeColor::CYAN => Ids::CYAN_GLAZED_TERRACOTTA,
- DyeColor::GRAY => Ids::GRAY_GLAZED_TERRACOTTA,
- DyeColor::GREEN => Ids::GREEN_GLAZED_TERRACOTTA,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_GLAZED_TERRACOTTA,
- DyeColor::LIGHT_GRAY => Ids::SILVER_GLAZED_TERRACOTTA,
- DyeColor::LIME => Ids::LIME_GLAZED_TERRACOTTA,
- DyeColor::MAGENTA => Ids::MAGENTA_GLAZED_TERRACOTTA,
- DyeColor::ORANGE => Ids::ORANGE_GLAZED_TERRACOTTA,
- DyeColor::PINK => Ids::PINK_GLAZED_TERRACOTTA,
- DyeColor::PURPLE => Ids::PURPLE_GLAZED_TERRACOTTA,
- DyeColor::RED => Ids::RED_GLAZED_TERRACOTTA,
- DyeColor::WHITE => Ids::WHITE_GLAZED_TERRACOTTA,
- DyeColor::YELLOW => Ids::YELLOW_GLAZED_TERRACOTTA,
- })
- ->writeHorizontalFacing($block->getFacing());
- });
-
- $this->map(Blocks::WOOL(), fn(Wool $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_WOOL,
- DyeColor::BLUE => Ids::BLUE_WOOL,
- DyeColor::BROWN => Ids::BROWN_WOOL,
- DyeColor::CYAN => Ids::CYAN_WOOL,
- DyeColor::GRAY => Ids::GRAY_WOOL,
- DyeColor::GREEN => Ids::GREEN_WOOL,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_WOOL,
- DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_WOOL,
- DyeColor::LIME => Ids::LIME_WOOL,
- DyeColor::MAGENTA => Ids::MAGENTA_WOOL,
- DyeColor::ORANGE => Ids::ORANGE_WOOL,
- DyeColor::PINK => Ids::PINK_WOOL,
- DyeColor::PURPLE => Ids::PURPLE_WOOL,
- DyeColor::RED => Ids::RED_WOOL,
- DyeColor::WHITE => Ids::WHITE_WOOL,
- DyeColor::YELLOW => Ids::YELLOW_WOOL,
- }));
-
- $this->map(Blocks::CARPET(), fn(Carpet $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_CARPET,
- DyeColor::BLUE => Ids::BLUE_CARPET,
- DyeColor::BROWN => Ids::BROWN_CARPET,
- DyeColor::CYAN => Ids::CYAN_CARPET,
- DyeColor::GRAY => Ids::GRAY_CARPET,
- DyeColor::GREEN => Ids::GREEN_CARPET,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_CARPET,
- DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_CARPET,
- DyeColor::LIME => Ids::LIME_CARPET,
- DyeColor::MAGENTA => Ids::MAGENTA_CARPET,
- DyeColor::ORANGE => Ids::ORANGE_CARPET,
- DyeColor::PINK => Ids::PINK_CARPET,
- DyeColor::PURPLE => Ids::PURPLE_CARPET,
- DyeColor::RED => Ids::RED_CARPET,
- DyeColor::WHITE => Ids::WHITE_CARPET,
- DyeColor::YELLOW => Ids::YELLOW_CARPET,
- }));
-
- $this->map(Blocks::DYED_SHULKER_BOX(), fn(DyedShulkerBox $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_SHULKER_BOX,
- DyeColor::BLUE => Ids::BLUE_SHULKER_BOX,
- DyeColor::BROWN => Ids::BROWN_SHULKER_BOX,
- DyeColor::CYAN => Ids::CYAN_SHULKER_BOX,
- DyeColor::GRAY => Ids::GRAY_SHULKER_BOX,
- DyeColor::GREEN => Ids::GREEN_SHULKER_BOX,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_SHULKER_BOX,
- DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_SHULKER_BOX,
- DyeColor::LIME => Ids::LIME_SHULKER_BOX,
- DyeColor::MAGENTA => Ids::MAGENTA_SHULKER_BOX,
- DyeColor::ORANGE => Ids::ORANGE_SHULKER_BOX,
- DyeColor::PINK => Ids::PINK_SHULKER_BOX,
- DyeColor::PURPLE => Ids::PURPLE_SHULKER_BOX,
- DyeColor::RED => Ids::RED_SHULKER_BOX,
- DyeColor::WHITE => Ids::WHITE_SHULKER_BOX,
- DyeColor::YELLOW => Ids::YELLOW_SHULKER_BOX,
- }));
-
- $this->map(Blocks::CONCRETE(), fn(Concrete $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_CONCRETE,
- DyeColor::BLUE => Ids::BLUE_CONCRETE,
- DyeColor::BROWN => Ids::BROWN_CONCRETE,
- DyeColor::CYAN => Ids::CYAN_CONCRETE,
- DyeColor::GRAY => Ids::GRAY_CONCRETE,
- DyeColor::GREEN => Ids::GREEN_CONCRETE,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_CONCRETE,
- DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_CONCRETE,
- DyeColor::LIME => Ids::LIME_CONCRETE,
- DyeColor::MAGENTA => Ids::MAGENTA_CONCRETE,
- DyeColor::ORANGE => Ids::ORANGE_CONCRETE,
- DyeColor::PINK => Ids::PINK_CONCRETE,
- DyeColor::PURPLE => Ids::PURPLE_CONCRETE,
- DyeColor::RED => Ids::RED_CONCRETE,
- DyeColor::WHITE => Ids::WHITE_CONCRETE,
- DyeColor::YELLOW => Ids::YELLOW_CONCRETE,
- }));
-
- $this->map(Blocks::CONCRETE_POWDER(), fn(ConcretePowder $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_CONCRETE_POWDER,
- DyeColor::BLUE => Ids::BLUE_CONCRETE_POWDER,
- DyeColor::BROWN => Ids::BROWN_CONCRETE_POWDER,
- DyeColor::CYAN => Ids::CYAN_CONCRETE_POWDER,
- DyeColor::GRAY => Ids::GRAY_CONCRETE_POWDER,
- DyeColor::GREEN => Ids::GREEN_CONCRETE_POWDER,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_CONCRETE_POWDER,
- DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_CONCRETE_POWDER,
- DyeColor::LIME => Ids::LIME_CONCRETE_POWDER,
- DyeColor::MAGENTA => Ids::MAGENTA_CONCRETE_POWDER,
- DyeColor::ORANGE => Ids::ORANGE_CONCRETE_POWDER,
- DyeColor::PINK => Ids::PINK_CONCRETE_POWDER,
- DyeColor::PURPLE => Ids::PURPLE_CONCRETE_POWDER,
- DyeColor::RED => Ids::RED_CONCRETE_POWDER,
- DyeColor::WHITE => Ids::WHITE_CONCRETE_POWDER,
- DyeColor::YELLOW => Ids::YELLOW_CONCRETE_POWDER,
- }));
-
- $this->map(Blocks::STAINED_CLAY(), fn(StainedHardenedClay $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_TERRACOTTA,
- DyeColor::BLUE => Ids::BLUE_TERRACOTTA,
- DyeColor::BROWN => Ids::BROWN_TERRACOTTA,
- DyeColor::CYAN => Ids::CYAN_TERRACOTTA,
- DyeColor::GRAY => Ids::GRAY_TERRACOTTA,
- DyeColor::GREEN => Ids::GREEN_TERRACOTTA,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_TERRACOTTA,
- DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_TERRACOTTA,
- DyeColor::LIME => Ids::LIME_TERRACOTTA,
- DyeColor::MAGENTA => Ids::MAGENTA_TERRACOTTA,
- DyeColor::ORANGE => Ids::ORANGE_TERRACOTTA,
- DyeColor::PINK => Ids::PINK_TERRACOTTA,
- DyeColor::PURPLE => Ids::PURPLE_TERRACOTTA,
- DyeColor::RED => Ids::RED_TERRACOTTA,
- DyeColor::WHITE => Ids::WHITE_TERRACOTTA,
- DyeColor::YELLOW => Ids::YELLOW_TERRACOTTA,
- }));
-
- $this->map(Blocks::STAINED_GLASS(), fn(StainedGlass $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_STAINED_GLASS,
- DyeColor::BLUE => Ids::BLUE_STAINED_GLASS,
- DyeColor::BROWN => Ids::BROWN_STAINED_GLASS,
- DyeColor::CYAN => Ids::CYAN_STAINED_GLASS,
- DyeColor::GRAY => Ids::GRAY_STAINED_GLASS,
- DyeColor::GREEN => Ids::GREEN_STAINED_GLASS,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_STAINED_GLASS,
- DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_STAINED_GLASS,
- DyeColor::LIME => Ids::LIME_STAINED_GLASS,
- DyeColor::MAGENTA => Ids::MAGENTA_STAINED_GLASS,
- DyeColor::ORANGE => Ids::ORANGE_STAINED_GLASS,
- DyeColor::PINK => Ids::PINK_STAINED_GLASS,
- DyeColor::PURPLE => Ids::PURPLE_STAINED_GLASS,
- DyeColor::RED => Ids::RED_STAINED_GLASS,
- DyeColor::WHITE => Ids::WHITE_STAINED_GLASS,
- DyeColor::YELLOW => Ids::YELLOW_STAINED_GLASS,
- }));
-
- $this->map(Blocks::STAINED_GLASS_PANE(), fn(StainedGlassPane $block) => Writer::create(match($block->getColor()){
- DyeColor::BLACK => Ids::BLACK_STAINED_GLASS_PANE,
- DyeColor::BLUE => Ids::BLUE_STAINED_GLASS_PANE,
- DyeColor::BROWN => Ids::BROWN_STAINED_GLASS_PANE,
- DyeColor::CYAN => Ids::CYAN_STAINED_GLASS_PANE,
- DyeColor::GRAY => Ids::GRAY_STAINED_GLASS_PANE,
- DyeColor::GREEN => Ids::GREEN_STAINED_GLASS_PANE,
- DyeColor::LIGHT_BLUE => Ids::LIGHT_BLUE_STAINED_GLASS_PANE,
- DyeColor::LIGHT_GRAY => Ids::LIGHT_GRAY_STAINED_GLASS_PANE,
- DyeColor::LIME => Ids::LIME_STAINED_GLASS_PANE,
- DyeColor::MAGENTA => Ids::MAGENTA_STAINED_GLASS_PANE,
- DyeColor::ORANGE => Ids::ORANGE_STAINED_GLASS_PANE,
- DyeColor::PINK => Ids::PINK_STAINED_GLASS_PANE,
- DyeColor::PURPLE => Ids::PURPLE_STAINED_GLASS_PANE,
- DyeColor::RED => Ids::RED_STAINED_GLASS_PANE,
- DyeColor::WHITE => Ids::WHITE_STAINED_GLASS_PANE,
- DyeColor::YELLOW => Ids::YELLOW_STAINED_GLASS_PANE,
- }));
- }
-
- private function registerFlatCoralSerializers() : void{
- $this->map(Blocks::CORAL(), fn(Coral $block) => Writer::create(
- match($block->getCoralType()){
- CoralType::BRAIN => $block->isDead() ? Ids::DEAD_BRAIN_CORAL : Ids::BRAIN_CORAL,
- CoralType::BUBBLE => $block->isDead() ? Ids::DEAD_BUBBLE_CORAL : Ids::BUBBLE_CORAL,
- CoralType::FIRE => $block->isDead() ? Ids::DEAD_FIRE_CORAL : Ids::FIRE_CORAL,
- CoralType::HORN => $block->isDead() ? Ids::DEAD_HORN_CORAL : Ids::HORN_CORAL,
- CoralType::TUBE => $block->isDead() ? Ids::DEAD_TUBE_CORAL : Ids::TUBE_CORAL,
- }
- ));
-
- $this->map(Blocks::CORAL_FAN(), fn(FloorCoralFan $block) => Writer::create(
- match($block->getCoralType()){
- CoralType::BRAIN => $block->isDead() ? Ids::DEAD_BRAIN_CORAL_FAN : Ids::BRAIN_CORAL_FAN,
- CoralType::BUBBLE => $block->isDead() ? Ids::DEAD_BUBBLE_CORAL_FAN : Ids::BUBBLE_CORAL_FAN,
- CoralType::FIRE => $block->isDead() ? Ids::DEAD_FIRE_CORAL_FAN : Ids::FIRE_CORAL_FAN,
- CoralType::HORN => $block->isDead() ? Ids::DEAD_HORN_CORAL_FAN : Ids::HORN_CORAL_FAN,
- CoralType::TUBE => $block->isDead() ? Ids::DEAD_TUBE_CORAL_FAN : Ids::TUBE_CORAL_FAN,
- })
- ->writeInt(StateNames::CORAL_FAN_DIRECTION, match($axis = $block->getAxis()){
- Axis::X => 0,
- Axis::Z => 1,
- default => throw new BlockStateSerializeException("Invalid axis {$axis}"),
- }));
-
- $this->map(Blocks::CORAL_BLOCK(), fn(CoralBlock $block) => Writer::create(
- match($block->getCoralType()){
- CoralType::BRAIN => $block->isDead() ? Ids::DEAD_BRAIN_CORAL_BLOCK : Ids::BRAIN_CORAL_BLOCK,
- CoralType::BUBBLE => $block->isDead() ? Ids::DEAD_BUBBLE_CORAL_BLOCK : Ids::BUBBLE_CORAL_BLOCK,
- CoralType::FIRE => $block->isDead() ? Ids::DEAD_FIRE_CORAL_BLOCK : Ids::FIRE_CORAL_BLOCK,
- CoralType::HORN => $block->isDead() ? Ids::DEAD_HORN_CORAL_BLOCK : Ids::HORN_CORAL_BLOCK,
- 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{
- $this->map(Blocks::CAULDRON(), fn() => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_WATER, 0));
- $this->map(Blocks::LAVA_CAULDRON(), fn(FillableCauldron $b) => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_LAVA, $b->getFillLevel()));
- //potion cauldrons store their real information in the block actor data
- $this->map(Blocks::POTION_CAULDRON(), fn(FillableCauldron $b) => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_WATER, $b->getFillLevel()));
- $this->map(Blocks::WATER_CAULDRON(), fn(FillableCauldron $b) => Helper::encodeCauldron(StringValues::CAULDRON_LIQUID_WATER, $b->getFillLevel()));
- }
-
- private function registerFlatWoodBlockSerializers() : void{
- $this->map(Blocks::ACACIA_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::ACACIA_BUTTON)));
- $this->map(Blocks::ACACIA_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::ACACIA_DOOR)));
- $this->map(Blocks::ACACIA_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::ACACIA_FENCE_GATE)));
- $this->map(Blocks::ACACIA_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::ACACIA_PRESSURE_PLATE)));
- $this->map(Blocks::ACACIA_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::ACACIA_STANDING_SIGN)));
- $this->map(Blocks::ACACIA_STAIRS(), fn(WoodenStairs $block) => Helper::encodeStairs($block, new Writer(Ids::ACACIA_STAIRS)));
- $this->map(Blocks::ACACIA_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::ACACIA_TRAPDOOR)));
- $this->map(Blocks::ACACIA_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::ACACIA_WALL_SIGN)));
- $this->mapLog(Blocks::ACACIA_LOG(), Ids::ACACIA_LOG, Ids::STRIPPED_ACACIA_LOG);
- $this->mapLog(Blocks::ACACIA_WOOD(), Ids::ACACIA_WOOD, Ids::STRIPPED_ACACIA_WOOD);
- $this->mapSimple(Blocks::ACACIA_FENCE(), Ids::ACACIA_FENCE);
- $this->mapSimple(Blocks::ACACIA_PLANKS(), Ids::ACACIA_PLANKS);
- $this->mapSlab(Blocks::ACACIA_SLAB(), Ids::ACACIA_SLAB, Ids::ACACIA_DOUBLE_SLAB);
-
- $this->map(Blocks::BIRCH_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::BIRCH_BUTTON)));
- $this->map(Blocks::BIRCH_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::BIRCH_DOOR)));
- $this->map(Blocks::BIRCH_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::BIRCH_FENCE_GATE)));
- $this->map(Blocks::BIRCH_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::BIRCH_PRESSURE_PLATE)));
- $this->map(Blocks::BIRCH_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::BIRCH_STANDING_SIGN)));
- $this->map(Blocks::BIRCH_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::BIRCH_TRAPDOOR)));
- $this->map(Blocks::BIRCH_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::BIRCH_WALL_SIGN)));
- $this->mapLog(Blocks::BIRCH_LOG(), Ids::BIRCH_LOG, Ids::STRIPPED_BIRCH_LOG);
- $this->mapLog(Blocks::BIRCH_WOOD(), Ids::BIRCH_WOOD, Ids::STRIPPED_BIRCH_WOOD);
- $this->mapSimple(Blocks::BIRCH_FENCE(), Ids::BIRCH_FENCE);
- $this->mapSimple(Blocks::BIRCH_PLANKS(), Ids::BIRCH_PLANKS);
- $this->mapSlab(Blocks::BIRCH_SLAB(), Ids::BIRCH_SLAB, Ids::BIRCH_DOUBLE_SLAB);
- $this->mapStairs(Blocks::BIRCH_STAIRS(), Ids::BIRCH_STAIRS);
-
- $this->map(Blocks::CHERRY_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::CHERRY_BUTTON)));
- $this->map(Blocks::CHERRY_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::CHERRY_DOOR)));
- $this->map(Blocks::CHERRY_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::CHERRY_FENCE_GATE)));
- $this->map(Blocks::CHERRY_LOG(), fn(Wood $block) => Helper::encodeLog($block, Ids::CHERRY_LOG, Ids::STRIPPED_CHERRY_LOG));
- $this->map(Blocks::CHERRY_PRESSURE_PLATE(), fn(SimplePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::CHERRY_PRESSURE_PLATE)));
- $this->map(Blocks::CHERRY_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::CHERRY_STANDING_SIGN)));
- $this->map(Blocks::CHERRY_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::CHERRY_TRAPDOOR)));
- $this->map(Blocks::CHERRY_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::CHERRY_WALL_SIGN)));
- $this->mapSimple(Blocks::CHERRY_FENCE(), Ids::CHERRY_FENCE);
- $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->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)));
- $this->map(Blocks::CRIMSON_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::CRIMSON_FENCE_GATE)));
- $this->map(Blocks::CRIMSON_HYPHAE(), fn(Wood $block) => Helper::encodeLog($block, Ids::CRIMSON_HYPHAE, Ids::STRIPPED_CRIMSON_HYPHAE));
- $this->map(Blocks::CRIMSON_PRESSURE_PLATE(), fn(SimplePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::CRIMSON_PRESSURE_PLATE)));
- $this->map(Blocks::CRIMSON_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::CRIMSON_STANDING_SIGN)));
- $this->map(Blocks::CRIMSON_STEM(), fn(Wood $block) => Helper::encodeLog($block, Ids::CRIMSON_STEM, Ids::STRIPPED_CRIMSON_STEM));
- $this->map(Blocks::CRIMSON_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::CRIMSON_TRAPDOOR)));
- $this->map(Blocks::CRIMSON_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::CRIMSON_WALL_SIGN)));
- $this->mapSimple(Blocks::CRIMSON_FENCE(), Ids::CRIMSON_FENCE);
- $this->mapSimple(Blocks::CRIMSON_PLANKS(), Ids::CRIMSON_PLANKS);
- $this->mapSlab(Blocks::CRIMSON_SLAB(), Ids::CRIMSON_SLAB, Ids::CRIMSON_DOUBLE_SLAB);
- $this->mapStairs(Blocks::CRIMSON_STAIRS(), Ids::CRIMSON_STAIRS);
-
- $this->map(Blocks::DARK_OAK_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::DARK_OAK_BUTTON)));
- $this->map(Blocks::DARK_OAK_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::DARK_OAK_DOOR)));
- $this->map(Blocks::DARK_OAK_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::DARK_OAK_FENCE_GATE)));
- $this->map(Blocks::DARK_OAK_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::DARK_OAK_PRESSURE_PLATE)));
- $this->map(Blocks::DARK_OAK_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::DARKOAK_STANDING_SIGN)));
- $this->map(Blocks::DARK_OAK_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::DARK_OAK_TRAPDOOR)));
- $this->map(Blocks::DARK_OAK_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::DARKOAK_WALL_SIGN)));
- $this->mapLog(Blocks::DARK_OAK_LOG(), Ids::DARK_OAK_LOG, Ids::STRIPPED_DARK_OAK_LOG);
- $this->mapLog(Blocks::DARK_OAK_WOOD(), Ids::DARK_OAK_WOOD, Ids::STRIPPED_DARK_OAK_WOOD);
- $this->mapSimple(Blocks::DARK_OAK_FENCE(), Ids::DARK_OAK_FENCE);
- $this->mapSimple(Blocks::DARK_OAK_PLANKS(), Ids::DARK_OAK_PLANKS);
- $this->mapSlab(Blocks::DARK_OAK_SLAB(), Ids::DARK_OAK_SLAB, Ids::DARK_OAK_DOUBLE_SLAB);
- $this->mapStairs(Blocks::DARK_OAK_STAIRS(), Ids::DARK_OAK_STAIRS);
-
- $this->map(Blocks::JUNGLE_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::JUNGLE_BUTTON)));
- $this->map(Blocks::JUNGLE_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::JUNGLE_DOOR)));
- $this->map(Blocks::JUNGLE_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::JUNGLE_FENCE_GATE)));
- $this->map(Blocks::JUNGLE_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::JUNGLE_PRESSURE_PLATE)));
- $this->map(Blocks::JUNGLE_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::JUNGLE_STANDING_SIGN)));
- $this->map(Blocks::JUNGLE_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::JUNGLE_TRAPDOOR)));
- $this->map(Blocks::JUNGLE_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::JUNGLE_WALL_SIGN)));
- $this->mapLog(Blocks::JUNGLE_LOG(), Ids::JUNGLE_LOG, Ids::STRIPPED_JUNGLE_LOG);
- $this->mapLog(Blocks::JUNGLE_WOOD(), Ids::JUNGLE_WOOD, Ids::STRIPPED_JUNGLE_WOOD);
- $this->mapSimple(Blocks::JUNGLE_FENCE(), Ids::JUNGLE_FENCE);
- $this->mapSimple(Blocks::JUNGLE_PLANKS(), Ids::JUNGLE_PLANKS);
- $this->mapSlab(Blocks::JUNGLE_SLAB(), Ids::JUNGLE_SLAB, Ids::JUNGLE_DOUBLE_SLAB);
- $this->mapStairs(Blocks::JUNGLE_STAIRS(), Ids::JUNGLE_STAIRS);
-
- $this->map(Blocks::MANGROVE_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::MANGROVE_BUTTON)));
- $this->map(Blocks::MANGROVE_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::MANGROVE_DOOR)));
- $this->map(Blocks::MANGROVE_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::MANGROVE_FENCE_GATE)));
- $this->map(Blocks::MANGROVE_LOG(), fn(Wood $block) => Helper::encodeLog($block, Ids::MANGROVE_LOG, Ids::STRIPPED_MANGROVE_LOG));
- $this->map(Blocks::MANGROVE_PRESSURE_PLATE(), fn(SimplePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::MANGROVE_PRESSURE_PLATE)));
- $this->map(Blocks::MANGROVE_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::MANGROVE_STANDING_SIGN)));
- $this->map(Blocks::MANGROVE_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::MANGROVE_TRAPDOOR)));
- $this->map(Blocks::MANGROVE_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::MANGROVE_WALL_SIGN)));
- $this->mapSimple(Blocks::MANGROVE_FENCE(), Ids::MANGROVE_FENCE);
- $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->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)));
- $this->map(Blocks::OAK_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::FENCE_GATE)));
- $this->map(Blocks::OAK_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::WOODEN_PRESSURE_PLATE)));
- $this->map(Blocks::OAK_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::STANDING_SIGN)));
- $this->map(Blocks::OAK_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::TRAPDOOR)));
- $this->map(Blocks::OAK_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::WALL_SIGN)));
- $this->mapLog(Blocks::OAK_LOG(), Ids::OAK_LOG, Ids::STRIPPED_OAK_LOG);
- $this->mapLog(Blocks::OAK_WOOD(), Ids::OAK_WOOD, Ids::STRIPPED_OAK_WOOD);
- $this->mapSimple(Blocks::OAK_FENCE(), Ids::OAK_FENCE);
- $this->mapSimple(Blocks::OAK_PLANKS(), Ids::OAK_PLANKS);
- $this->mapSlab(Blocks::OAK_SLAB(), Ids::OAK_SLAB, Ids::OAK_DOUBLE_SLAB);
- $this->mapStairs(Blocks::OAK_STAIRS(), Ids::OAK_STAIRS);
-
- $this->map(Blocks::PALE_OAK_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::PALE_OAK_BUTTON)));
- $this->map(Blocks::PALE_OAK_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::PALE_OAK_DOOR)));
- $this->map(Blocks::PALE_OAK_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::PALE_OAK_FENCE_GATE)));
- $this->map(Blocks::PALE_OAK_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::PALE_OAK_PRESSURE_PLATE)));
- $this->map(Blocks::PALE_OAK_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::PALE_OAK_STANDING_SIGN)));
- $this->map(Blocks::PALE_OAK_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::PALE_OAK_TRAPDOOR)));
- $this->map(Blocks::PALE_OAK_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::PALE_OAK_WALL_SIGN)));
- $this->mapLog(Blocks::PALE_OAK_LOG(), Ids::PALE_OAK_LOG, Ids::STRIPPED_PALE_OAK_LOG);
- $this->mapLog(Blocks::PALE_OAK_WOOD(), Ids::PALE_OAK_WOOD, Ids::STRIPPED_PALE_OAK_WOOD);
- $this->mapSimple(Blocks::PALE_OAK_FENCE(), Ids::PALE_OAK_FENCE);
- $this->mapSimple(Blocks::PALE_OAK_PLANKS(), Ids::PALE_OAK_PLANKS);
- $this->mapSlab(Blocks::PALE_OAK_SLAB(), Ids::PALE_OAK_SLAB, Ids::PALE_OAK_DOUBLE_SLAB);
- $this->mapStairs(Blocks::PALE_OAK_STAIRS(), Ids::PALE_OAK_STAIRS);
-
- $this->map(Blocks::SPRUCE_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::SPRUCE_BUTTON)));
- $this->map(Blocks::SPRUCE_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::SPRUCE_DOOR)));
- $this->map(Blocks::SPRUCE_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::SPRUCE_FENCE_GATE)));
- $this->map(Blocks::SPRUCE_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::SPRUCE_PRESSURE_PLATE)));
- $this->map(Blocks::SPRUCE_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::SPRUCE_STANDING_SIGN)));
- $this->map(Blocks::SPRUCE_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::SPRUCE_TRAPDOOR)));
- $this->map(Blocks::SPRUCE_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::SPRUCE_WALL_SIGN)));
- $this->mapLog(Blocks::SPRUCE_LOG(), Ids::SPRUCE_LOG, Ids::STRIPPED_SPRUCE_LOG);
- $this->mapLog(Blocks::SPRUCE_WOOD(), Ids::SPRUCE_WOOD, Ids::STRIPPED_SPRUCE_WOOD);
- $this->mapSimple(Blocks::SPRUCE_FENCE(), Ids::SPRUCE_FENCE);
- $this->mapSimple(Blocks::SPRUCE_PLANKS(), Ids::SPRUCE_PLANKS);
- $this->mapSlab(Blocks::SPRUCE_SLAB(), Ids::SPRUCE_SLAB, Ids::SPRUCE_DOUBLE_SLAB);
- $this->mapStairs(Blocks::SPRUCE_STAIRS(), Ids::SPRUCE_STAIRS);
- //wood and slabs still use the old way of storing wood type
-
- $this->map(Blocks::WARPED_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::WARPED_BUTTON)));
- $this->map(Blocks::WARPED_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::WARPED_DOOR)));
- $this->map(Blocks::WARPED_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::WARPED_FENCE_GATE)));
- $this->map(Blocks::WARPED_HYPHAE(), fn(Wood $block) => Helper::encodeLog($block, Ids::WARPED_HYPHAE, Ids::STRIPPED_WARPED_HYPHAE));
- $this->map(Blocks::WARPED_PRESSURE_PLATE(), fn(SimplePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::WARPED_PRESSURE_PLATE)));
- $this->map(Blocks::WARPED_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::WARPED_STANDING_SIGN)));
- $this->map(Blocks::WARPED_STEM(), fn(Wood $block) => Helper::encodeLog($block, Ids::WARPED_STEM, Ids::STRIPPED_WARPED_STEM));
- $this->map(Blocks::WARPED_TRAPDOOR(), fn(Trapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::WARPED_TRAPDOOR)));
- $this->map(Blocks::WARPED_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::WARPED_WALL_SIGN)));
- $this->mapSimple(Blocks::WARPED_FENCE(), Ids::WARPED_FENCE);
- $this->mapSimple(Blocks::WARPED_PLANKS(), Ids::WARPED_PLANKS);
- $this->mapSlab(Blocks::WARPED_SLAB(), Ids::WARPED_SLAB, Ids::WARPED_DOUBLE_SLAB);
- $this->mapStairs(Blocks::WARPED_STAIRS(), Ids::WARPED_STAIRS);
- }
-
- private function registerLeavesSerializers() : void{
- //flattened IDs
- $this->map(Blocks::AZALEA_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::AZALEA_LEAVES)));
- $this->map(Blocks::CHERRY_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::CHERRY_LEAVES)));
- $this->map(Blocks::FLOWERING_AZALEA_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::AZALEA_LEAVES_FLOWERED)));
- $this->map(Blocks::MANGROVE_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::MANGROVE_LEAVES)));
- $this->map(Blocks::PALE_OAK_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::PALE_OAK_LEAVES)));
-
- //legacy mess
- $this->map(Blocks::ACACIA_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::ACACIA_LEAVES)));
- $this->map(Blocks::BIRCH_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::BIRCH_LEAVES)));
- $this->map(Blocks::DARK_OAK_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::DARK_OAK_LEAVES)));
- $this->map(Blocks::JUNGLE_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::JUNGLE_LEAVES)));
- $this->map(Blocks::OAK_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::OAK_LEAVES)));
- $this->map(Blocks::SPRUCE_LEAVES(), fn(Leaves $block) => Helper::encodeLeaves($block, new Writer(Ids::SPRUCE_LEAVES)));
- }
-
- private function registerSaplingSerializers() : void{
- foreach([
- Ids::ACACIA_SAPLING => Blocks::ACACIA_SAPLING(),
- Ids::BIRCH_SAPLING => Blocks::BIRCH_SAPLING(),
- Ids::DARK_OAK_SAPLING => Blocks::DARK_OAK_SAPLING(),
- Ids::JUNGLE_SAPLING => Blocks::JUNGLE_SAPLING(),
- Ids::OAK_SAPLING => Blocks::OAK_SAPLING(),
- Ids::SPRUCE_SAPLING => Blocks::SPRUCE_SAPLING(),
- ] as $id => $block){
- $this->map($block, fn(Sapling $block) => Helper::encodeSapling($block, new Writer($id)));
- }
- }
-
- 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 registerCopperSerializers() : void{
- $this->map(Blocks::COPPER(), function(Copper $block) : Writer{
- $oxidation = $block->getOxidation();
- return new Writer($block->isWaxed() ?
- Helper::selectCopperId($oxidation, Ids::WAXED_COPPER, Ids::WAXED_EXPOSED_COPPER, Ids::WAXED_WEATHERED_COPPER, Ids::WAXED_OXIDIZED_COPPER) :
- 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() ?
- Helper::selectCopperId($oxidation, Ids::WAXED_CUT_COPPER, Ids::WAXED_EXPOSED_CUT_COPPER, Ids::WAXED_WEATHERED_CUT_COPPER, Ids::WAXED_OXIDIZED_CUT_COPPER) :
- Helper::selectCopperId($oxidation, Ids::CUT_COPPER, Ids::EXPOSED_CUT_COPPER, Ids::WEATHERED_CUT_COPPER, Ids::OXIDIZED_CUT_COPPER)
- );
- });
- $this->map(Blocks::CUT_COPPER_SLAB(), function(CopperSlab $block) : Writer{
- $oxidation = $block->getOxidation();
- return Helper::encodeSlab(
- $block,
- ($block->isWaxed() ?
- Helper::selectCopperId(
- $oxidation,
- Ids::WAXED_CUT_COPPER_SLAB,
- Ids::WAXED_EXPOSED_CUT_COPPER_SLAB,
- Ids::WAXED_WEATHERED_CUT_COPPER_SLAB,
- Ids::WAXED_OXIDIZED_CUT_COPPER_SLAB
- ) :
- Helper::selectCopperId(
- $oxidation,
- Ids::CUT_COPPER_SLAB,
- Ids::EXPOSED_CUT_COPPER_SLAB,
- Ids::WEATHERED_CUT_COPPER_SLAB,
- Ids::OXIDIZED_CUT_COPPER_SLAB
- )
- ),
- ($block->isWaxed() ?
- Helper::selectCopperId(
- $oxidation,
- Ids::WAXED_DOUBLE_CUT_COPPER_SLAB,
- Ids::WAXED_EXPOSED_DOUBLE_CUT_COPPER_SLAB,
- Ids::WAXED_WEATHERED_DOUBLE_CUT_COPPER_SLAB,
- Ids::WAXED_OXIDIZED_DOUBLE_CUT_COPPER_SLAB
- ) :
- Helper::selectCopperId(
- $oxidation,
- Ids::DOUBLE_CUT_COPPER_SLAB,
- Ids::EXPOSED_DOUBLE_CUT_COPPER_SLAB,
- Ids::WEATHERED_DOUBLE_CUT_COPPER_SLAB,
- Ids::OXIDIZED_DOUBLE_CUT_COPPER_SLAB
- )
- )
- );
- });
- $this->map(Blocks::CUT_COPPER_STAIRS(), function(CopperStairs $block) : Writer{
- $oxidation = $block->getOxidation();
- return Helper::encodeStairs(
- $block,
- new Writer($block->isWaxed() ?
- Helper::selectCopperId(
- $oxidation,
- Ids::WAXED_CUT_COPPER_STAIRS,
- Ids::WAXED_EXPOSED_CUT_COPPER_STAIRS,
- Ids::WAXED_WEATHERED_CUT_COPPER_STAIRS,
- Ids::WAXED_OXIDIZED_CUT_COPPER_STAIRS
- ) :
- Helper::selectCopperId(
- $oxidation,
- Ids::CUT_COPPER_STAIRS,
- Ids::EXPOSED_CUT_COPPER_STAIRS,
- Ids::WEATHERED_CUT_COPPER_STAIRS,
- Ids::OXIDIZED_CUT_COPPER_STAIRS
- )
- )
- );
- });
- $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
- )
- )
- );
- });
- }
-
- private function registerSimpleSerializers() : void{
- $this->mapSimple(Blocks::AIR(), Ids::AIR);
- $this->mapSimple(Blocks::AMETHYST(), Ids::AMETHYST_BLOCK);
- $this->mapSimple(Blocks::ANCIENT_DEBRIS(), Ids::ANCIENT_DEBRIS);
- $this->mapSimple(Blocks::ANDESITE(), Ids::ANDESITE);
- $this->mapSimple(Blocks::BARRIER(), Ids::BARRIER);
- $this->mapSimple(Blocks::BEACON(), Ids::BEACON);
- $this->mapSimple(Blocks::BLACKSTONE(), Ids::BLACKSTONE);
- $this->mapSimple(Blocks::BLUE_ICE(), Ids::BLUE_ICE);
- $this->mapSimple(Blocks::BOOKSHELF(), Ids::BOOKSHELF);
- $this->mapSimple(Blocks::BRICKS(), Ids::BRICK_BLOCK);
- $this->mapSimple(Blocks::BROWN_MUSHROOM(), Ids::BROWN_MUSHROOM);
- $this->mapSimple(Blocks::BUDDING_AMETHYST(), Ids::BUDDING_AMETHYST);
- $this->mapSimple(Blocks::CALCITE(), Ids::CALCITE);
- $this->mapSimple(Blocks::CARTOGRAPHY_TABLE(), Ids::CARTOGRAPHY_TABLE);
- $this->mapSimple(Blocks::CHEMICAL_HEAT(), Ids::CHEMICAL_HEAT);
- $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_RESIN_BRICKS(), Ids::CHISELED_RESIN_BRICKS);
- $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);
- $this->mapSimple(Blocks::COAL_ORE(), Ids::COAL_ORE);
- $this->mapSimple(Blocks::COBBLED_DEEPSLATE(), Ids::COBBLED_DEEPSLATE);
- $this->mapSimple(Blocks::COBBLESTONE(), Ids::COBBLESTONE);
- $this->mapSimple(Blocks::COBWEB(), Ids::WEB);
- $this->mapSimple(Blocks::COPPER_ORE(), Ids::COPPER_ORE);
- $this->mapSimple(Blocks::CRACKED_DEEPSLATE_BRICKS(), Ids::CRACKED_DEEPSLATE_BRICKS);
- $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::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);
- $this->mapSimple(Blocks::DEEPSLATE_COPPER_ORE(), Ids::DEEPSLATE_COPPER_ORE);
- $this->mapSimple(Blocks::DEEPSLATE_DIAMOND_ORE(), Ids::DEEPSLATE_DIAMOND_ORE);
- $this->mapSimple(Blocks::DEEPSLATE_EMERALD_ORE(), Ids::DEEPSLATE_EMERALD_ORE);
- $this->mapSimple(Blocks::DEEPSLATE_GOLD_ORE(), Ids::DEEPSLATE_GOLD_ORE);
- $this->mapSimple(Blocks::DEEPSLATE_IRON_ORE(), Ids::DEEPSLATE_IRON_ORE);
- $this->mapSimple(Blocks::DEEPSLATE_LAPIS_LAZULI_ORE(), Ids::DEEPSLATE_LAPIS_ORE);
- $this->mapSimple(Blocks::DEEPSLATE_TILES(), Ids::DEEPSLATE_TILES);
- $this->mapSimple(Blocks::DIAMOND(), Ids::DIAMOND_BLOCK);
- $this->mapSimple(Blocks::DIAMOND_ORE(), Ids::DIAMOND_ORE);
- $this->mapSimple(Blocks::DIORITE(), Ids::DIORITE);
- $this->mapSimple(Blocks::DRAGON_EGG(), Ids::DRAGON_EGG);
- $this->mapSimple(Blocks::DRIED_KELP(), Ids::DRIED_KELP_BLOCK);
- $this->mapSimple(Blocks::ELEMENT_ACTINIUM(), Ids::ELEMENT_89);
- $this->mapSimple(Blocks::ELEMENT_ALUMINUM(), Ids::ELEMENT_13);
- $this->mapSimple(Blocks::ELEMENT_AMERICIUM(), Ids::ELEMENT_95);
- $this->mapSimple(Blocks::ELEMENT_ANTIMONY(), Ids::ELEMENT_51);
- $this->mapSimple(Blocks::ELEMENT_ARGON(), Ids::ELEMENT_18);
- $this->mapSimple(Blocks::ELEMENT_ARSENIC(), Ids::ELEMENT_33);
- $this->mapSimple(Blocks::ELEMENT_ASTATINE(), Ids::ELEMENT_85);
- $this->mapSimple(Blocks::ELEMENT_BARIUM(), Ids::ELEMENT_56);
- $this->mapSimple(Blocks::ELEMENT_BERKELIUM(), Ids::ELEMENT_97);
- $this->mapSimple(Blocks::ELEMENT_BERYLLIUM(), Ids::ELEMENT_4);
- $this->mapSimple(Blocks::ELEMENT_BISMUTH(), Ids::ELEMENT_83);
- $this->mapSimple(Blocks::ELEMENT_BOHRIUM(), Ids::ELEMENT_107);
- $this->mapSimple(Blocks::ELEMENT_BORON(), Ids::ELEMENT_5);
- $this->mapSimple(Blocks::ELEMENT_BROMINE(), Ids::ELEMENT_35);
- $this->mapSimple(Blocks::ELEMENT_CADMIUM(), Ids::ELEMENT_48);
- $this->mapSimple(Blocks::ELEMENT_CALCIUM(), Ids::ELEMENT_20);
- $this->mapSimple(Blocks::ELEMENT_CALIFORNIUM(), Ids::ELEMENT_98);
- $this->mapSimple(Blocks::ELEMENT_CARBON(), Ids::ELEMENT_6);
- $this->mapSimple(Blocks::ELEMENT_CERIUM(), Ids::ELEMENT_58);
- $this->mapSimple(Blocks::ELEMENT_CESIUM(), Ids::ELEMENT_55);
- $this->mapSimple(Blocks::ELEMENT_CHLORINE(), Ids::ELEMENT_17);
- $this->mapSimple(Blocks::ELEMENT_CHROMIUM(), Ids::ELEMENT_24);
- $this->mapSimple(Blocks::ELEMENT_COBALT(), Ids::ELEMENT_27);
- $this->mapSimple(Blocks::ELEMENT_COPERNICIUM(), Ids::ELEMENT_112);
- $this->mapSimple(Blocks::ELEMENT_COPPER(), Ids::ELEMENT_29);
- $this->mapSimple(Blocks::ELEMENT_CURIUM(), Ids::ELEMENT_96);
- $this->mapSimple(Blocks::ELEMENT_DARMSTADTIUM(), Ids::ELEMENT_110);
- $this->mapSimple(Blocks::ELEMENT_DUBNIUM(), Ids::ELEMENT_105);
- $this->mapSimple(Blocks::ELEMENT_DYSPROSIUM(), Ids::ELEMENT_66);
- $this->mapSimple(Blocks::ELEMENT_EINSTEINIUM(), Ids::ELEMENT_99);
- $this->mapSimple(Blocks::ELEMENT_ERBIUM(), Ids::ELEMENT_68);
- $this->mapSimple(Blocks::ELEMENT_EUROPIUM(), Ids::ELEMENT_63);
- $this->mapSimple(Blocks::ELEMENT_FERMIUM(), Ids::ELEMENT_100);
- $this->mapSimple(Blocks::ELEMENT_FLEROVIUM(), Ids::ELEMENT_114);
- $this->mapSimple(Blocks::ELEMENT_FLUORINE(), Ids::ELEMENT_9);
- $this->mapSimple(Blocks::ELEMENT_FRANCIUM(), Ids::ELEMENT_87);
- $this->mapSimple(Blocks::ELEMENT_GADOLINIUM(), Ids::ELEMENT_64);
- $this->mapSimple(Blocks::ELEMENT_GALLIUM(), Ids::ELEMENT_31);
- $this->mapSimple(Blocks::ELEMENT_GERMANIUM(), Ids::ELEMENT_32);
- $this->mapSimple(Blocks::ELEMENT_GOLD(), Ids::ELEMENT_79);
- $this->mapSimple(Blocks::ELEMENT_HAFNIUM(), Ids::ELEMENT_72);
- $this->mapSimple(Blocks::ELEMENT_HASSIUM(), Ids::ELEMENT_108);
- $this->mapSimple(Blocks::ELEMENT_HELIUM(), Ids::ELEMENT_2);
- $this->mapSimple(Blocks::ELEMENT_HOLMIUM(), Ids::ELEMENT_67);
- $this->mapSimple(Blocks::ELEMENT_HYDROGEN(), Ids::ELEMENT_1);
- $this->mapSimple(Blocks::ELEMENT_INDIUM(), Ids::ELEMENT_49);
- $this->mapSimple(Blocks::ELEMENT_IODINE(), Ids::ELEMENT_53);
- $this->mapSimple(Blocks::ELEMENT_IRIDIUM(), Ids::ELEMENT_77);
- $this->mapSimple(Blocks::ELEMENT_IRON(), Ids::ELEMENT_26);
- $this->mapSimple(Blocks::ELEMENT_KRYPTON(), Ids::ELEMENT_36);
- $this->mapSimple(Blocks::ELEMENT_LANTHANUM(), Ids::ELEMENT_57);
- $this->mapSimple(Blocks::ELEMENT_LAWRENCIUM(), Ids::ELEMENT_103);
- $this->mapSimple(Blocks::ELEMENT_LEAD(), Ids::ELEMENT_82);
- $this->mapSimple(Blocks::ELEMENT_LITHIUM(), Ids::ELEMENT_3);
- $this->mapSimple(Blocks::ELEMENT_LIVERMORIUM(), Ids::ELEMENT_116);
- $this->mapSimple(Blocks::ELEMENT_LUTETIUM(), Ids::ELEMENT_71);
- $this->mapSimple(Blocks::ELEMENT_MAGNESIUM(), Ids::ELEMENT_12);
- $this->mapSimple(Blocks::ELEMENT_MANGANESE(), Ids::ELEMENT_25);
- $this->mapSimple(Blocks::ELEMENT_MEITNERIUM(), Ids::ELEMENT_109);
- $this->mapSimple(Blocks::ELEMENT_MENDELEVIUM(), Ids::ELEMENT_101);
- $this->mapSimple(Blocks::ELEMENT_MERCURY(), Ids::ELEMENT_80);
- $this->mapSimple(Blocks::ELEMENT_MOLYBDENUM(), Ids::ELEMENT_42);
- $this->mapSimple(Blocks::ELEMENT_MOSCOVIUM(), Ids::ELEMENT_115);
- $this->mapSimple(Blocks::ELEMENT_NEODYMIUM(), Ids::ELEMENT_60);
- $this->mapSimple(Blocks::ELEMENT_NEON(), Ids::ELEMENT_10);
- $this->mapSimple(Blocks::ELEMENT_NEPTUNIUM(), Ids::ELEMENT_93);
- $this->mapSimple(Blocks::ELEMENT_NICKEL(), Ids::ELEMENT_28);
- $this->mapSimple(Blocks::ELEMENT_NIHONIUM(), Ids::ELEMENT_113);
- $this->mapSimple(Blocks::ELEMENT_NIOBIUM(), Ids::ELEMENT_41);
- $this->mapSimple(Blocks::ELEMENT_NITROGEN(), Ids::ELEMENT_7);
- $this->mapSimple(Blocks::ELEMENT_NOBELIUM(), Ids::ELEMENT_102);
- $this->mapSimple(Blocks::ELEMENT_OGANESSON(), Ids::ELEMENT_118);
- $this->mapSimple(Blocks::ELEMENT_OSMIUM(), Ids::ELEMENT_76);
- $this->mapSimple(Blocks::ELEMENT_OXYGEN(), Ids::ELEMENT_8);
- $this->mapSimple(Blocks::ELEMENT_PALLADIUM(), Ids::ELEMENT_46);
- $this->mapSimple(Blocks::ELEMENT_PHOSPHORUS(), Ids::ELEMENT_15);
- $this->mapSimple(Blocks::ELEMENT_PLATINUM(), Ids::ELEMENT_78);
- $this->mapSimple(Blocks::ELEMENT_PLUTONIUM(), Ids::ELEMENT_94);
- $this->mapSimple(Blocks::ELEMENT_POLONIUM(), Ids::ELEMENT_84);
- $this->mapSimple(Blocks::ELEMENT_POTASSIUM(), Ids::ELEMENT_19);
- $this->mapSimple(Blocks::ELEMENT_PRASEODYMIUM(), Ids::ELEMENT_59);
- $this->mapSimple(Blocks::ELEMENT_PROMETHIUM(), Ids::ELEMENT_61);
- $this->mapSimple(Blocks::ELEMENT_PROTACTINIUM(), Ids::ELEMENT_91);
- $this->mapSimple(Blocks::ELEMENT_RADIUM(), Ids::ELEMENT_88);
- $this->mapSimple(Blocks::ELEMENT_RADON(), Ids::ELEMENT_86);
- $this->mapSimple(Blocks::ELEMENT_RHENIUM(), Ids::ELEMENT_75);
- $this->mapSimple(Blocks::ELEMENT_RHODIUM(), Ids::ELEMENT_45);
- $this->mapSimple(Blocks::ELEMENT_ROENTGENIUM(), Ids::ELEMENT_111);
- $this->mapSimple(Blocks::ELEMENT_RUBIDIUM(), Ids::ELEMENT_37);
- $this->mapSimple(Blocks::ELEMENT_RUTHENIUM(), Ids::ELEMENT_44);
- $this->mapSimple(Blocks::ELEMENT_RUTHERFORDIUM(), Ids::ELEMENT_104);
- $this->mapSimple(Blocks::ELEMENT_SAMARIUM(), Ids::ELEMENT_62);
- $this->mapSimple(Blocks::ELEMENT_SCANDIUM(), Ids::ELEMENT_21);
- $this->mapSimple(Blocks::ELEMENT_SEABORGIUM(), Ids::ELEMENT_106);
- $this->mapSimple(Blocks::ELEMENT_SELENIUM(), Ids::ELEMENT_34);
- $this->mapSimple(Blocks::ELEMENT_SILICON(), Ids::ELEMENT_14);
- $this->mapSimple(Blocks::ELEMENT_SILVER(), Ids::ELEMENT_47);
- $this->mapSimple(Blocks::ELEMENT_SODIUM(), Ids::ELEMENT_11);
- $this->mapSimple(Blocks::ELEMENT_STRONTIUM(), Ids::ELEMENT_38);
- $this->mapSimple(Blocks::ELEMENT_SULFUR(), Ids::ELEMENT_16);
- $this->mapSimple(Blocks::ELEMENT_TANTALUM(), Ids::ELEMENT_73);
- $this->mapSimple(Blocks::ELEMENT_TECHNETIUM(), Ids::ELEMENT_43);
- $this->mapSimple(Blocks::ELEMENT_TELLURIUM(), Ids::ELEMENT_52);
- $this->mapSimple(Blocks::ELEMENT_TENNESSINE(), Ids::ELEMENT_117);
- $this->mapSimple(Blocks::ELEMENT_TERBIUM(), Ids::ELEMENT_65);
- $this->mapSimple(Blocks::ELEMENT_THALLIUM(), Ids::ELEMENT_81);
- $this->mapSimple(Blocks::ELEMENT_THORIUM(), Ids::ELEMENT_90);
- $this->mapSimple(Blocks::ELEMENT_THULIUM(), Ids::ELEMENT_69);
- $this->mapSimple(Blocks::ELEMENT_TIN(), Ids::ELEMENT_50);
- $this->mapSimple(Blocks::ELEMENT_TITANIUM(), Ids::ELEMENT_22);
- $this->mapSimple(Blocks::ELEMENT_TUNGSTEN(), Ids::ELEMENT_74);
- $this->mapSimple(Blocks::ELEMENT_URANIUM(), Ids::ELEMENT_92);
- $this->mapSimple(Blocks::ELEMENT_VANADIUM(), Ids::ELEMENT_23);
- $this->mapSimple(Blocks::ELEMENT_XENON(), Ids::ELEMENT_54);
- $this->mapSimple(Blocks::ELEMENT_YTTERBIUM(), Ids::ELEMENT_70);
- $this->mapSimple(Blocks::ELEMENT_YTTRIUM(), Ids::ELEMENT_39);
- $this->mapSimple(Blocks::ELEMENT_ZERO(), Ids::ELEMENT_0);
- $this->mapSimple(Blocks::ELEMENT_ZINC(), Ids::ELEMENT_30);
- $this->mapSimple(Blocks::ELEMENT_ZIRCONIUM(), Ids::ELEMENT_40);
- $this->mapSimple(Blocks::EMERALD(), Ids::EMERALD_BLOCK);
- $this->mapSimple(Blocks::EMERALD_ORE(), Ids::EMERALD_ORE);
- $this->mapSimple(Blocks::ENCHANTING_TABLE(), Ids::ENCHANTING_TABLE);
- $this->mapSimple(Blocks::END_STONE(), Ids::END_STONE);
- $this->mapSimple(Blocks::END_STONE_BRICKS(), Ids::END_BRICKS);
- $this->mapSimple(Blocks::FERN(), Ids::FERN);
- $this->mapSimple(Blocks::FLETCHING_TABLE(), Ids::FLETCHING_TABLE);
- $this->mapSimple(Blocks::GILDED_BLACKSTONE(), Ids::GILDED_BLACKSTONE);
- $this->mapSimple(Blocks::GLASS(), Ids::GLASS);
- $this->mapSimple(Blocks::GLASS_PANE(), Ids::GLASS_PANE);
- $this->mapSimple(Blocks::GLOWING_OBSIDIAN(), Ids::GLOWINGOBSIDIAN);
- $this->mapSimple(Blocks::GLOWSTONE(), Ids::GLOWSTONE);
- $this->mapSimple(Blocks::GOLD(), Ids::GOLD_BLOCK);
- $this->mapSimple(Blocks::GOLD_ORE(), Ids::GOLD_ORE);
- $this->mapSimple(Blocks::GRANITE(), Ids::GRANITE);
- $this->mapSimple(Blocks::GRASS(), Ids::GRASS_BLOCK);
- $this->mapSimple(Blocks::GRASS_PATH(), Ids::GRASS_PATH);
- $this->mapSimple(Blocks::GRAVEL(), Ids::GRAVEL);
- $this->mapSimple(Blocks::HANGING_ROOTS(), Ids::HANGING_ROOTS);
- $this->mapSimple(Blocks::HARDENED_CLAY(), Ids::HARDENED_CLAY);
- $this->mapSimple(Blocks::HARDENED_GLASS(), Ids::HARD_GLASS);
- $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);
- $this->mapSimple(Blocks::IRON(), Ids::IRON_BLOCK);
- $this->mapSimple(Blocks::IRON_BARS(), Ids::IRON_BARS);
- $this->mapSimple(Blocks::IRON_ORE(), Ids::IRON_ORE);
- $this->mapSimple(Blocks::JUKEBOX(), Ids::JUKEBOX);
- $this->mapSimple(Blocks::LAPIS_LAZULI(), Ids::LAPIS_BLOCK);
- $this->mapSimple(Blocks::LAPIS_LAZULI_ORE(), Ids::LAPIS_ORE);
- $this->mapSimple(Blocks::LEGACY_STONECUTTER(), Ids::STONECUTTER);
- $this->mapSimple(Blocks::LILY_PAD(), Ids::WATERLILY);
- $this->mapSimple(Blocks::MAGMA(), Ids::MAGMA);
- $this->mapSimple(Blocks::MANGROVE_ROOTS(), Ids::MANGROVE_ROOTS);
- $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);
- $this->mapSimple(Blocks::NETHERITE(), Ids::NETHERITE_BLOCK);
- $this->mapSimple(Blocks::NETHERRACK(), Ids::NETHERRACK);
- $this->mapSimple(Blocks::NETHER_BRICKS(), Ids::NETHER_BRICK);
- $this->mapSimple(Blocks::NETHER_BRICK_FENCE(), Ids::NETHER_BRICK_FENCE);
- $this->mapSimple(Blocks::NETHER_GOLD_ORE(), Ids::NETHER_GOLD_ORE);
- $this->mapSimple(Blocks::NETHER_QUARTZ_ORE(), Ids::QUARTZ_ORE);
- $this->mapSimple(Blocks::NETHER_REACTOR_CORE(), Ids::NETHERREACTOR);
- $this->mapSimple(Blocks::NETHER_WART_BLOCK(), Ids::NETHER_WART_BLOCK);
- $this->mapSimple(Blocks::NOTE_BLOCK(), Ids::NOTEBLOCK);
- $this->mapSimple(Blocks::OBSIDIAN(), Ids::OBSIDIAN);
- $this->mapSimple(Blocks::PACKED_ICE(), Ids::PACKED_ICE);
- $this->mapSimple(Blocks::PACKED_MUD(), Ids::PACKED_MUD);
- $this->mapSimple(Blocks::PODZOL(), Ids::PODZOL);
- $this->mapSimple(Blocks::POLISHED_ANDESITE(), Ids::POLISHED_ANDESITE);
- $this->mapSimple(Blocks::POLISHED_BLACKSTONE(), Ids::POLISHED_BLACKSTONE);
- $this->mapSimple(Blocks::POLISHED_BLACKSTONE_BRICKS(), Ids::POLISHED_BLACKSTONE_BRICKS);
- $this->mapSimple(Blocks::POLISHED_DEEPSLATE(), Ids::POLISHED_DEEPSLATE);
- $this->mapSimple(Blocks::POLISHED_DIORITE(), Ids::POLISHED_DIORITE);
- $this->mapSimple(Blocks::POLISHED_GRANITE(), Ids::POLISHED_GRANITE);
- $this->mapSimple(Blocks::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);
- $this->mapSimple(Blocks::RAW_IRON(), Ids::RAW_IRON_BLOCK);
- $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::RESIN(), Ids::RESIN_BLOCK);
- $this->mapSimple(Blocks::RESIN_BRICKS(), Ids::RESIN_BRICKS);
- $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);
- $this->mapSimple(Blocks::SHULKER_BOX(), Ids::UNDYED_SHULKER_BOX);
- $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::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);
-
- $this->mapSimple(Blocks::ALLIUM(), Ids::ALLIUM);
- $this->mapSimple(Blocks::CORNFLOWER(), Ids::CORNFLOWER);
- $this->mapSimple(Blocks::AZURE_BLUET(), Ids::AZURE_BLUET);
- $this->mapSimple(Blocks::LILY_OF_THE_VALLEY(), Ids::LILY_OF_THE_VALLEY);
- $this->mapSimple(Blocks::BLUE_ORCHID(), Ids::BLUE_ORCHID);
- $this->mapSimple(Blocks::OXEYE_DAISY(), Ids::OXEYE_DAISY);
- $this->mapSimple(Blocks::POPPY(), Ids::POPPY);
- $this->mapSimple(Blocks::ORANGE_TULIP(), Ids::ORANGE_TULIP);
- $this->mapSimple(Blocks::PINK_TULIP(), Ids::PINK_TULIP);
- $this->mapSimple(Blocks::RED_TULIP(), Ids::RED_TULIP);
- $this->mapSimple(Blocks::WHITE_TULIP(), Ids::WHITE_TULIP);
- }
-
- private function registerSerializers() : void{
- $this->map(Blocks::ACTIVATOR_RAIL(), function(ActivatorRail $block) : Writer{
- return Writer::create(Ids::ACTIVATOR_RAIL)
- ->writeBool(StateNames::RAIL_DATA_BIT, $block->isPowered())
- ->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
- });
- $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()){
- AmethystCluster::STAGE_SMALL_BUD => Ids::SMALL_AMETHYST_BUD,
- AmethystCluster::STAGE_MEDIUM_BUD => Ids::MEDIUM_AMETHYST_BUD,
- AmethystCluster::STAGE_LARGE_BUD => Ids::LARGE_AMETHYST_BUD,
- AmethystCluster::STAGE_CLUSTER => Ids::AMETHYST_CLUSTER,
- default => throw new BlockStateSerializeException("Invalid Amethyst Cluster stage $stage"),
- })
- ->writeBlockFace($block->getFacing())
- );
- $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::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())
- ->writeString(StateNames::BAMBOO_LEAF_SIZE, match($block->getLeafSize()){
- Bamboo::NO_LEAVES => StringValues::BAMBOO_LEAF_SIZE_NO_LEAVES,
- Bamboo::SMALL_LEAVES => StringValues::BAMBOO_LEAF_SIZE_SMALL_LEAVES,
- Bamboo::LARGE_LEAVES => StringValues::BAMBOO_LEAF_SIZE_LARGE_LEAVES,
- default => throw new BlockStateSerializeException("Invalid Bamboo leaf thickness " . $block->getLeafSize()),
- })
- ->writeString(StateNames::BAMBOO_STALK_THICKNESS, $block->isThick() ? StringValues::BAMBOO_STALK_THICKNESS_THICK : StringValues::BAMBOO_STALK_THICKNESS_THIN);
- });
- $this->map(Blocks::BAMBOO_SAPLING(), function(BambooSapling $block) : Writer{
- return Writer::create(Ids::BAMBOO_SAPLING)
- ->writeBool(StateNames::AGE_BIT, $block->isReady());
- });
- $this->map(Blocks::BANNER(), function(FloorBanner $block) : Writer{
- return Writer::create(Ids::STANDING_BANNER)
- ->writeInt(StateNames::GROUND_SIGN_DIRECTION, $block->getRotation());
- });
- $this->map(Blocks::BARREL(), function(Barrel $block) : Writer{
- return Writer::create(Ids::BARREL)
- ->writeBool(StateNames::OPEN_BIT, $block->isOpen())
- ->writeFacingDirection($block->getFacing());
- });
- $this->map(Blocks::BASALT(), function(SimplePillar $block) : Writer{
- return Writer::create(Ids::BASALT)
- ->writePillarAxis($block->getAxis());
- });
- $this->map(Blocks::BED(), function(Bed $block) : Writer{
- return Writer::create(Ids::BED)
- ->writeBool(StateNames::HEAD_PIECE_BIT, $block->isHeadPart())
- ->writeBool(StateNames::OCCUPIED_BIT, $block->isOccupied())
- ->writeLegacyHorizontalFacing($block->getFacing());
- });
- $this->map(Blocks::BEDROCK(), function(Block $block) : Writer{
- return Writer::create(Ids::BEDROCK)
- ->writeBool(StateNames::INFINIBURN_BIT, $block->burnsForever());
- });
- $this->map(Blocks::BEETROOTS(), fn(Beetroot $block) => Helper::encodeCrops($block, new Writer(Ids::BEETROOT)));
- $this->map(Blocks::BELL(), function(Bell $block) : Writer{
- return Writer::create(Ids::BELL)
- ->writeBellAttachmentType($block->getAttachmentType())
- ->writeBool(StateNames::TOGGLE_BIT, false) //we don't care about this; it's just to keep MCPE happy
- ->writeLegacyHorizontalFacing($block->getFacing());
-
- });
- $this->map(Blocks::BIG_DRIPLEAF_HEAD(), function(BigDripleafHead $block) : Writer{
- return Writer::create(Ids::BIG_DRIPLEAF)
- ->writeCardinalHorizontalFacing($block->getFacing())
- ->writeString(StateNames::BIG_DRIPLEAF_TILT, match($block->getLeafState()){
- DripleafState::STABLE => StringValues::BIG_DRIPLEAF_TILT_NONE,
- DripleafState::UNSTABLE => StringValues::BIG_DRIPLEAF_TILT_UNSTABLE,
- DripleafState::PARTIAL_TILT => StringValues::BIG_DRIPLEAF_TILT_PARTIAL_TILT,
- DripleafState::FULL_TILT => StringValues::BIG_DRIPLEAF_TILT_FULL_TILT,
- })
- ->writeBool(StateNames::BIG_DRIPLEAF_HEAD, true);
- });
- $this->map(Blocks::BIG_DRIPLEAF_STEM(), function(BigDripleafStem $block) : Writer{
- return Writer::create(Ids::BIG_DRIPLEAF)
- ->writeCardinalHorizontalFacing($block->getFacing())
- ->writeString(StateNames::BIG_DRIPLEAF_TILT, StringValues::BIG_DRIPLEAF_TILT_NONE)
- ->writeBool(StateNames::BIG_DRIPLEAF_HEAD, false);
- });
- $this->mapSlab(Blocks::BLACKSTONE_SLAB(), Ids::BLACKSTONE_SLAB, Ids::BLACKSTONE_DOUBLE_SLAB);
- $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::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)
- ->writePillarAxis($block->getAxis());
- });
- $this->map(Blocks::BREWING_STAND(), function(BrewingStand $block) : Writer{
- return Writer::create(Ids::BREWING_STAND)
- ->writeBool(StateNames::BREWING_STAND_SLOT_A_BIT, $block->hasSlot(BrewingStandSlot::EAST))
- ->writeBool(StateNames::BREWING_STAND_SLOT_B_BIT, $block->hasSlot(BrewingStandSlot::SOUTHWEST))
- ->writeBool(StateNames::BREWING_STAND_SLOT_C_BIT, $block->hasSlot(BrewingStandSlot::NORTHWEST));
- });
- $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::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)
- ->writeInt(StateNames::AGE, $block->getAge());
- });
- $this->map(Blocks::CAKE(), function(Cake $block) : Writer{
- 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)
- ->writeCardinalHorizontalFacing($block->getFacing());
- });
- $this->map(Blocks::CAVE_VINES(), function(CaveVines $block) : Writer{
- //I have no idea why this only has 3 IDs - there are 4 in Java and 4 visually distinct states in Bedrock
- return Writer::create($block->hasBerries() ?
- ($block->isHead() ?
- Ids::CAVE_VINES_HEAD_WITH_BERRIES :
- Ids::CAVE_VINES_BODY_WITH_BERRIES
- ) :
- Ids::CAVE_VINES
- )
- ->writeInt(StateNames::GROWING_PLANT_AGE, $block->getAge());
- });
- $this->map(Blocks::CHAIN(), function(Chain $block) : Writer{
- return Writer::create(Ids::CHAIN)
- ->writePillarAxis($block->getAxis());
- });
- $this->map(Blocks::CHEST(), function(Chest $block) : Writer{
- return Writer::create(Ids::CHEST)
- ->writeCardinalHorizontalFacing($block->getFacing());
- });
- $this->map(Blocks::CHISELED_BOOKSHELF(), function(ChiseledBookshelf $block) : Writer{
- $flags = 0;
- foreach($block->getSlots() as $slot){
- $flags |= 1 << $slot->value;
- }
- return Writer::create(Ids::CHISELED_BOOKSHELF)
- ->writeLegacyHorizontalFacing($block->getFacing())
- ->writeInt(StateNames::BOOKS_STORED, $flags);
- });
- $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());
- });
- $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->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::encodeWall($block, Writer::create(Ids::COBBLESTONE_WALL)));
- $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, 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)
- ->writeInt(StateNames::REDSTONE_SIGNAL, $block->getOutputSignalStrength());
- });
- $this->map(Blocks::DEEPSLATE(), function(SimplePillar $block) : Writer{
- return Writer::create(Ids::DEEPSLATE)
- ->writePillarAxis($block->getAxis());
- });
- $this->mapSlab(Blocks::DEEPSLATE_BRICK_SLAB(), Ids::DEEPSLATE_BRICK_SLAB, Ids::DEEPSLATE_BRICK_DOUBLE_SLAB);
- $this->mapStairs(Blocks::DEEPSLATE_BRICK_STAIRS(), Ids::DEEPSLATE_BRICK_STAIRS);
- $this->map(Blocks::DEEPSLATE_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::DEEPSLATE_BRICK_WALL)));
- $this->map(Blocks::DEEPSLATE_REDSTONE_ORE(), fn(RedstoneOre $block) => new Writer($block->isLit() ? Ids::LIT_DEEPSLATE_REDSTONE_ORE : Ids::DEEPSLATE_REDSTONE_ORE));
- $this->mapSlab(Blocks::DEEPSLATE_TILE_SLAB(), Ids::DEEPSLATE_TILE_SLAB, Ids::DEEPSLATE_TILE_DOUBLE_SLAB);
- $this->mapStairs(Blocks::DEEPSLATE_TILE_STAIRS(), Ids::DEEPSLATE_TILE_STAIRS);
- $this->map(Blocks::DEEPSLATE_TILE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::DEEPSLATE_TILE_WALL)));
- $this->map(Blocks::DETECTOR_RAIL(), function(DetectorRail $block) : Writer{
- return Writer::create(Ids::DETECTOR_RAIL)
- ->writeBool(StateNames::RAIL_DATA_BIT, $block->isActivated())
- ->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
- });
- $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::encodeWall($block, Writer::create(Ids::DIORITE_WALL)));
- $this->map(Blocks::DIRT(), function(Dirt $block) : Writer{
- 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, Writer::create(Ids::ELEMENT_CONSTRUCTOR)));
- $this->map(Blocks::ENDER_CHEST(), function(EnderChest $block) : Writer{
- return Writer::create(Ids::ENDER_CHEST)
- ->writeCardinalHorizontalFacing($block->getFacing());
- });
- $this->map(Blocks::END_PORTAL_FRAME(), function(EndPortalFrame $block) : Writer{
- return Writer::create(Ids::END_PORTAL_FRAME)
- ->writeBool(StateNames::END_PORTAL_EYE_BIT, $block->hasEye())
- ->writeCardinalHorizontalFacing($block->getFacing());
- });
- $this->map(Blocks::END_ROD(), function(EndRod $block) : Writer{
- return Writer::create(Ids::END_ROD)
- ->writeEndRodFacingDirection($block->getFacing());
- });
- $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::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());
- });
- $this->map(Blocks::FIRE(), function(Fire $block) : Writer{
- return Writer::create(Ids::FIRE)
- ->writeInt(StateNames::AGE, $block->getAge());
- });
- $this->map(Blocks::FLOWER_POT(), function() : Writer{
- return Writer::create(Ids::FLOWER_POT)
- ->writeBool(StateNames::UPDATE_BIT, false); //to keep MCPE happy
- });
- $this->map(Blocks::FROGLIGHT(), function(Froglight $block){
- return Writer::create(match($block->getFroglightType()){
- FroglightType::OCHRE => Ids::OCHRE_FROGLIGHT,
- FroglightType::PEARLESCENT => Ids::PEARLESCENT_FROGLIGHT,
- FroglightType::VERDANT => Ids::VERDANT_FROGLIGHT,
- })
- ->writePillarAxis($block->getAxis());
- });
- $this->map(Blocks::FROSTED_ICE(), function(FrostedIce $block) : Writer{
- return Writer::create(Ids::FROSTED_ICE)
- ->writeInt(StateNames::AGE, $block->getAge());
- });
- $this->map(Blocks::FURNACE(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::FURNACE, Ids::LIT_FURNACE));
- $this->map(Blocks::GLOW_LICHEN(), function(GlowLichen $block) : Writer{
- return Writer::create(Ids::GLOW_LICHEN)
- ->writeFacingFlags($block->getFaces());
- });
- $this->map(Blocks::GLOWING_ITEM_FRAME(), fn(ItemFrame $block) => Helper::encodeItemFrame($block, Ids::GLOW_FRAME));
- $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::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)
- ->writePillarAxis($block->getAxis());
- });
- $this->map(Blocks::HOPPER(), function(Hopper $block) : Writer{
- return Writer::create(Ids::HOPPER)
- ->writeBool(StateNames::TOGGLE_BIT, $block->isPowered())
- ->writeFacingWithoutUp($block->getFacing());
- });
- $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, Writer::create(Ids::LAB_TABLE)));
- $this->map(Blocks::LADDER(), function(Ladder $block) : Writer{
- return Writer::create(Ids::LADDER)
- ->writeHorizontalFacing($block->getFacing());
- });
- $this->map(Blocks::LANTERN(), function(Lantern $block) : Writer{
- return Writer::create(Ids::LANTERN)
- ->writeBool(StateNames::HANGING, $block->isHanging());
- });
- $this->map(Blocks::LARGE_FERN(), fn(DoubleTallGrass $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::LARGE_FERN)));
- $this->map(Blocks::LAVA(), fn(Lava $block) => Helper::encodeLiquid($block, Ids::LAVA, Ids::FLOWING_LAVA));
- $this->map(Blocks::LECTERN(), function(Lectern $block) : Writer{
- return Writer::create(Ids::LECTERN)
- ->writeBool(StateNames::POWERED_BIT, $block->isProducingSignal())
- ->writeCardinalHorizontalFacing($block->getFacing());
- });
- $this->map(Blocks::LEVER(), function(Lever $block) : Writer{
- return Writer::create(Ids::LEVER)
- ->writeBool(StateNames::OPEN_BIT, $block->isActivated())
- ->writeString(StateNames::LEVER_DIRECTION, match($block->getFacing()){
- LeverFacing::DOWN_AXIS_Z => StringValues::LEVER_DIRECTION_DOWN_NORTH_SOUTH,
- LeverFacing::DOWN_AXIS_X => StringValues::LEVER_DIRECTION_DOWN_EAST_WEST,
- LeverFacing::UP_AXIS_Z => StringValues::LEVER_DIRECTION_UP_NORTH_SOUTH,
- LeverFacing::UP_AXIS_X => StringValues::LEVER_DIRECTION_UP_EAST_WEST,
- LeverFacing::NORTH => StringValues::LEVER_DIRECTION_NORTH,
- LeverFacing::SOUTH => StringValues::LEVER_DIRECTION_SOUTH,
- LeverFacing::WEST => StringValues::LEVER_DIRECTION_WEST,
- LeverFacing::EAST => StringValues::LEVER_DIRECTION_EAST,
- });
- });
- $this->map(Blocks::LIGHT(), function(Light $block) : Writer{
- 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)
- ->writeFacingDirection($block->getFacing());
- });
- $this->map(Blocks::LILAC(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::LILAC)));
- $this->map(Blocks::LIT_PUMPKIN(), function(LitPumpkin $block) : Writer{
- return Writer::create(Ids::LIT_PUMPKIN)
- ->writeCardinalHorizontalFacing($block->getFacing());
- });
- $this->map(Blocks::LOOM(), function(Loom $block) : Writer{
- return Writer::create(Ids::LOOM)
- ->writeLegacyHorizontalFacing($block->getFacing());
- });
- $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->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::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::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::MUSHROOM_STEM)
- ->writeInt(StateNames::HUGE_MUSHROOM_BITS, BlockLegacyMetadata::MUSHROOM_BLOCK_STEM));
- $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::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()){
- Axis::X => StringValues::PORTAL_AXIS_X,
- Axis::Z => StringValues::PORTAL_AXIS_Z,
- default => throw new BlockStateSerializeException("Invalid Nether Portal axis " . $block->getAxis()),
- });
- });
- $this->map(Blocks::NETHER_WART(), function(NetherWartPlant $block) : Writer{
- return Writer::create(Ids::NETHER_WART)
- ->writeInt(StateNames::AGE, $block->getAge());
- });
- $this->map(Blocks::PEONY(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::PEONY)));
- $this->map(Blocks::PINK_PETALS(), function(PinkPetals $block) : Writer{
- return Writer::create(Ids::PINK_PETALS)
- ->writeCardinalHorizontalFacing($block->getFacing())
- ->writeInt(StateNames::GROWTH, $block->getCount() - 1);
- });
- $this->map(Blocks::PITCHER_PLANT(), function(DoublePlant $block) : Writer{
- return Writer::create(Ids::PITCHER_PLANT)
- ->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop());
- });
- $this->map(Blocks::PITCHER_CROP(), function(PitcherCrop $block) : Writer{
- return Writer::create(Ids::PITCHER_CROP)
- ->writeInt(StateNames::GROWTH, $block->getAge())
- ->writeBool(StateNames::UPPER_BLOCK_BIT, false);
- });
- $this->map(Blocks::DOUBLE_PITCHER_CROP(), function(DoublePitcherCrop $block) : Writer{
- return Writer::create(Ids::PITCHER_CROP)
- ->writeInt(StateNames::GROWTH, $block->getAge() + 1 + PitcherCrop::MAX_AGE)
- ->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop());
- });
- $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)
- ->writePillarAxis($block->getAxis());
- });
- $this->mapSlab(Blocks::POLISHED_BLACKSTONE_BRICK_SLAB(), Ids::POLISHED_BLACKSTONE_BRICK_SLAB, Ids::POLISHED_BLACKSTONE_BRICK_DOUBLE_SLAB);
- $this->mapStairs(Blocks::POLISHED_BLACKSTONE_BRICK_STAIRS(), Ids::POLISHED_BLACKSTONE_BRICK_STAIRS);
- $this->map(Blocks::POLISHED_BLACKSTONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::POLISHED_BLACKSTONE_BRICK_WALL)));
- $this->map(Blocks::POLISHED_BLACKSTONE_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::POLISHED_BLACKSTONE_BUTTON)));
- $this->map(Blocks::POLISHED_BLACKSTONE_PRESSURE_PLATE(), fn(SimplePressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::POLISHED_BLACKSTONE_PRESSURE_PLATE)));
- $this->mapSlab(Blocks::POLISHED_BLACKSTONE_SLAB(), Ids::POLISHED_BLACKSTONE_SLAB, Ids::POLISHED_BLACKSTONE_DOUBLE_SLAB);
- $this->mapStairs(Blocks::POLISHED_BLACKSTONE_STAIRS(), Ids::POLISHED_BLACKSTONE_STAIRS);
- $this->map(Blocks::POLISHED_BLACKSTONE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::POLISHED_BLACKSTONE_WALL)));
- $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->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->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->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->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::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::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_PILLAR)
- ->writePillarAxis($block->getAxis());
- });
- $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(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)
- ->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
- });
- $this->map(Blocks::REDSTONE_COMPARATOR(), function(RedstoneComparator $block) : Writer{
- return Writer::create($block->isPowered() ? Ids::POWERED_COMPARATOR : Ids::UNPOWERED_COMPARATOR)
- ->writeBool(StateNames::OUTPUT_LIT_BIT, $block->isPowered())
- ->writeBool(StateNames::OUTPUT_SUBTRACT_BIT, $block->isSubtractMode())
- ->writeCardinalHorizontalFacing($block->getFacing());
- });
- $this->map(Blocks::REDSTONE_LAMP(), fn(RedstoneLamp $block) => new Writer($block->isPowered() ? Ids::LIT_REDSTONE_LAMP : Ids::REDSTONE_LAMP));
- $this->map(Blocks::REDSTONE_ORE(), fn(RedstoneOre $block) => new Writer($block->isLit() ? Ids::LIT_REDSTONE_ORE : Ids::REDSTONE_ORE));
- $this->map(Blocks::REDSTONE_REPEATER(), function(RedstoneRepeater $block) : Writer{
- return Writer::create($block->isPowered() ? Ids::POWERED_REPEATER : Ids::UNPOWERED_REPEATER)
- ->writeCardinalHorizontalFacing($block->getFacing())
- ->writeInt(StateNames::REPEATER_DELAY, $block->getDelay() - 1);
- });
- $this->map(Blocks::REDSTONE_TORCH(), function(RedstoneTorch $block) : Writer{
- return Writer::create($block->isLit() ? Ids::REDSTONE_TORCH : Ids::UNLIT_REDSTONE_TORCH)
- ->writeTorchFacing($block->getFacing());
- });
- $this->map(Blocks::REDSTONE_WIRE(), function(RedstoneWire $block) : Writer{
- return Writer::create(Ids::REDSTONE_WIRE)
- ->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->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::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::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->mapSlab(Blocks::RESIN_BRICK_SLAB(), Ids::RESIN_BRICK_SLAB, Ids::RESIN_BRICK_DOUBLE_SLAB);
- $this->map(Blocks::RESIN_BRICK_STAIRS(), fn(Stair $block) => Helper::encodeStairs($block, new Writer(Ids::RESIN_BRICK_STAIRS)));
- $this->map(Blocks::RESIN_BRICK_WALL(), fn(Wall $block) => Helper::encodeWall($block, Writer::create(Ids::RESIN_BRICK_WALL)));
- $this->map(Blocks::RESIN_CLUMP(), function(ResinClump $block) : Writer{
- return Writer::create(Ids::RESIN_CLUMP)
- ->writeFacingFlags($block->getFaces());
- });
- $this->map(Blocks::ROSE_BUSH(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::ROSE_BUSH)));
- $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::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())
- ->writeInt(StateNames::CLUSTER_COUNT, $block->getCount() - 1);
- });
- $this->map(Blocks::SMALL_DRIPLEAF(), function(SmallDripleaf $block) : Writer{
- return Writer::create(Ids::SMALL_DRIPLEAF_BLOCK)
- ->writeCardinalHorizontalFacing($block->getFacing())
- ->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(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->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->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->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
- });
- $this->map(Blocks::SOUL_LANTERN(), function(Lantern $block) : Writer{
- return Writer::create(Ids::SOUL_LANTERN)
- ->writeBool(StateNames::HANGING, $block->isHanging());
- });
- $this->map(Blocks::SOUL_TORCH(), function(Torch $block) : Writer{
- return Writer::create(Ids::SOUL_TORCH)
- ->writeTorchFacing($block->getFacing());
- });
- $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->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::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->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)
- ->writeInt(StateNames::AGE, $block->getAge());
- });
- $this->map(Blocks::SUNFLOWER(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::SUNFLOWER)));
- $this->map(Blocks::SWEET_BERRY_BUSH(), function(SweetBerryBush $block) : Writer{
- return Writer::create(Ids::SWEET_BERRY_BUSH)
- ->writeInt(StateNames::GROWTH, $block->getAge());
- });
- $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());
- });
- $this->map(Blocks::TORCHFLOWER_CROP(), function(TorchflowerCrop $block){
- return Writer::create(Ids::TORCHFLOWER_CROP)
- ->writeInt(StateNames::GROWTH, $block->isReady() ? 1 : 0);
- });
- $this->map(Blocks::TRAPPED_CHEST(), function(TrappedChest $block) : Writer{
- return Writer::create(Ids::TRAPPED_CHEST)
- ->writeCardinalHorizontalFacing($block->getFacing());
- });
- $this->map(Blocks::TRIPWIRE(), function(Tripwire $block) : Writer{
- return Writer::create(Ids::TRIP_WIRE)
- ->writeBool(StateNames::ATTACHED_BIT, $block->isConnected())
- ->writeBool(StateNames::DISARMED_BIT, $block->isDisarmed())
- ->writeBool(StateNames::POWERED_BIT, $block->isTriggered())
- ->writeBool(StateNames::SUSPENDED_BIT, $block->isSuspended());
- });
- $this->map(Blocks::TRIPWIRE_HOOK(), function(TripwireHook $block) : Writer{
- return Writer::create(Ids::TRIPWIRE_HOOK)
- ->writeBool(StateNames::ATTACHED_BIT, $block->isConnected())
- ->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());
- });
- $this->map(Blocks::UNDERWATER_TORCH(), function(UnderwaterTorch $block) : Writer{
- return Writer::create(Ids::UNDERWATER_TORCH)
- ->writeTorchFacing($block->getFacing());
- });
- $this->map(Blocks::VINES(), function(Vine $block) : Writer{
- return Writer::create(Ids::VINE)
- ->writeInt(StateNames::VINE_DIRECTION_BITS, ($block->hasFace(Facing::NORTH) ? BlockLegacyMetadata::VINE_FLAG_NORTH : 0) | ($block->hasFace(Facing::SOUTH) ? BlockLegacyMetadata::VINE_FLAG_SOUTH : 0) | ($block->hasFace(Facing::WEST) ? BlockLegacyMetadata::VINE_FLAG_WEST : 0) | ($block->hasFace(Facing::EAST) ? BlockLegacyMetadata::VINE_FLAG_EAST : 0));
- });
- $this->map(Blocks::WALL_BANNER(), function(WallBanner $block) : Writer{
- return Writer::create(Ids::WALL_BANNER)
- ->writeHorizontalFacing($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)
- ->writeInt(StateNames::WEEPING_VINES_AGE, $block->getAge());
- });
- $this->map(Blocks::WEIGHTED_PRESSURE_PLATE_HEAVY(), function(WeightedPressurePlate $block) : Writer{
- return Writer::create(Ids::HEAVY_WEIGHTED_PRESSURE_PLATE)
- ->writeInt(StateNames::REDSTONE_SIGNAL, $block->getOutputSignalStrength());
- });
- $this->map(Blocks::WEIGHTED_PRESSURE_PLATE_LIGHT(), function(WeightedPressurePlate $block) : Writer{
- return Writer::create(Ids::LIGHT_WEIGHTED_PRESSURE_PLATE)
- ->writeInt(StateNames::REDSTONE_SIGNAL, $block->getOutputSignalStrength());
- });
- $this->map(Blocks::WHEAT(), fn(Wheat $block) => Helper::encodeCrops($block, new Writer(Ids::WHEAT)));
+ return $result instanceof Writer ? $result->getBlockStateData() : $result;
}
}
diff --git a/src/data/bedrock/block/convert/BlockSerializerDeserializerRegistrar.php b/src/data/bedrock/block/convert/BlockSerializerDeserializerRegistrar.php
new file mode 100644
index 000000000..5fc1d3eef
--- /dev/null
+++ b/src/data/bedrock/block/convert/BlockSerializerDeserializerRegistrar.php
@@ -0,0 +1,237 @@
+> $components
+ *
+ * @return string[][]
+ * @phpstan-return list>
+ */
+ private static function compileFlattenedIdPartMatrix(array $components) : array{
+ $result = [];
+ foreach($components as $component){
+ $column = is_string($component) ? [$component] : $component->getPossibleValues();
+
+ if(count($result) === 0){
+ $result = array_map(fn($value) => [$value], $column);
+ }else{
+ $stepResult = [];
+ foreach($result as $parts){
+ foreach($column as $value){
+ $stepPart = $parts;
+ $stepPart[] = $value;
+ $stepResult[] = $stepPart;
+ }
+ }
+
+ $result = $stepResult;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * @param string[]|StringProperty[] $idComponents
+ *
+ * @phpstan-template TBlock of Block
+ *
+ * @phpstan-param TBlock $block
+ * @phpstan-param list> $idComponents
+ */
+ private static function serializeFlattenedId(Block $block, array $idComponents) : string{
+ $id = "";
+ foreach($idComponents as $infix){
+ $id .= is_string($infix) ? $infix : $infix->serializePlain($block);
+ }
+ return $id;
+ }
+
+ /**
+ * @param string[]|StringProperty[] $idComponents
+ * @param string[] $idPropertyValues
+ *
+ * @phpstan-template TBlock of Block
+ *
+ * @phpstan-param TBlock $baseBlock
+ * @phpstan-param list> $idComponents
+ * @phpstan-param list $idPropertyValues
+ *
+ * @phpstan-return TBlock
+ */
+ private static function deserializeFlattenedId(Block $baseBlock, array $idComponents, array $idPropertyValues) : Block{
+ $preparedBlock = clone $baseBlock;
+ foreach($idComponents as $k => $component){
+ if($component instanceof StringProperty){
+ $fakeValue = $idPropertyValues[$k];
+ $component->deserializePlain($preparedBlock, $fakeValue);
+ }
+ }
+
+ return $preparedBlock;
+ }
+
+ public function mapSimple(Block $block, string $id) : void{
+ $this->deserializer->map($id, fn() => clone $block);
+ $this->serializer->map($block, BlockStateData::current($id, []));
+ }
+
+ /**
+ * @phpstan-template TBlock of Block
+ * @phpstan-param FlattenedIdModel $model
+ */
+ public function mapFlattenedId(FlattenedIdModel $model) : void{
+ $block = $model->getBlock();
+
+ $idComponents = $model->getIdComponents();
+ if(count($idComponents) === 0){
+ throw new \InvalidArgumentException("No ID components provided");
+ }
+ $properties = $model->getProperties();
+
+ //This is a really cursed hack that lets us essentially write flattened properties as blockstate properties, and
+ //then pull them out to compile an ID :D
+ //This works surprisingly well and is much more elegant than I would've expected
+
+ if(count($properties) > 0){
+ $this->serializer->map($block, function(Block $block) use ($idComponents, $properties) : Writer{
+ $id = self::serializeFlattenedId($block, $idComponents);
+
+ $writer = new Writer($id);
+ foreach($properties as $property){
+ $property->serialize($block, $writer);
+ }
+
+ return $writer;
+ });
+ }else{
+ $this->serializer->map($block, function(Block $block) use ($idComponents) : BlockStateData{
+ //fast path for blocks with no state properties
+ $id = self::serializeFlattenedId($block, $idComponents);
+ return BlockStateData::current($id, []);
+ });
+ }
+
+ $idPermutations = self::compileFlattenedIdPartMatrix($idComponents);
+ foreach($idPermutations as $idParts){
+ //deconstruct the ID into a partial state
+ //we can do this at registration time since there will be multiple deserializers
+ $preparedBlock = self::deserializeFlattenedId($block, $idComponents, $idParts);
+ $id = implode("", $idParts);
+
+ if(count($properties) > 0){
+ $this->deserializer->map($id, function(Reader $reader) use ($preparedBlock, $properties) : Block{
+ $block = clone $preparedBlock;
+
+ foreach($properties as $property){
+ $property->deserialize($block, $reader);
+ }
+ return $block;
+ });
+ }else{
+ //fast path for blocks with no state properties
+ $this->deserializer->map($id, fn() => clone $preparedBlock);
+ }
+ }
+ }
+
+ /**
+ * @phpstan-template TBlock of Block&Colored
+ * @phpstan-param TBlock $block
+ */
+ public function mapColored(Block $block, string $idPrefix, string $idSuffix) : void{
+ $this->mapFlattenedId(FlattenedIdModel::create($block)
+ ->idComponents([
+ $idPrefix,
+ CommonProperties::getInstance()->dyeColorIdInfix,
+ $idSuffix
+ ])
+ );
+ }
+
+ public function mapSlab(Slab $block, string $type) : void{
+ $commonProperties = CommonProperties::getInstance();
+ $this->mapFlattenedId(FlattenedIdModel::create($block)
+ ->idComponents(["minecraft:", $type, "_", $commonProperties->slabIdInfix, "slab"])
+ ->properties([$commonProperties->slabPositionProperty])
+ );
+ }
+
+ public function mapStairs(Stair $block, string $id) : void{
+ $this->mapModel(Model::create($block, $id)->properties(CommonProperties::getInstance()->stairProperties));
+ }
+
+ /**
+ * @phpstan-template TBlock of Block
+ * @phpstan-param Model $model
+ */
+ public function mapModel(Model $model) : void{
+ $id = $model->getId();
+ $block = $model->getBlock();
+ $propertyDescriptors = $model->getProperties();
+
+ $this->deserializer->map($id, static function(Reader $in) use ($block, $propertyDescriptors) : Block{
+ $newBlock = clone $block;
+ foreach($propertyDescriptors as $descriptor){
+ $descriptor->deserialize($newBlock, $in);
+ }
+ return $newBlock;
+ });
+ $this->serializer->map($block, static function(Block $block) use ($id, $propertyDescriptors) : Writer{
+ $writer = new Writer($id);
+ foreach($propertyDescriptors as $descriptor){
+ $descriptor->serialize($block, $writer);
+ }
+ return $writer;
+ });
+ }
+}
diff --git a/src/data/bedrock/block/convert/BlockStateDeserializerHelper.php b/src/data/bedrock/block/convert/BlockStateDeserializerHelper.php
deleted file mode 100644
index 5cf3f7f76..000000000
--- a/src/data/bedrock/block/convert/BlockStateDeserializerHelper.php
+++ /dev/null
@@ -1,327 +0,0 @@
-setFacing($in->readFacingDirection())
- ->setPressed($in->readBool(BlockStateNames::BUTTON_PRESSED_BIT));
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeCandle(Candle $block, BlockStateReader $in) : Candle{
- return $block
- ->setCount($in->readBoundedInt(StateNames::CANDLES, 0, 3) + 1)
- ->setLit($in->readBool(StateNames::LIT));
- }
-
- /**
- * @phpstan-template TCrops of Crops
- * @phpstan-param TCrops $block
- * @phpstan-return TCrops
- *
- * @throws BlockStateDeserializeException
- */
- public static function decodeCrops(Crops $block, BlockStateReader $in) : Crops{
- return $block->setAge($in->readBoundedInt(BlockStateNames::GROWTH, 0, 7));
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeComparator(RedstoneComparator $block, BlockStateReader $in) : RedstoneComparator{
- return $block
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setPowered($in->readBool(BlockStateNames::OUTPUT_LIT_BIT))
- ->setSubtractMode($in->readBool(BlockStateNames::OUTPUT_SUBTRACT_BIT));
- }
-
- /**
- * @phpstan-template TBlock of CopperMaterial
- *
- * @phpstan-param TBlock $block
- * @phpstan-return TBlock
- */
- public static function decodeCopper(CopperMaterial $block, CopperOxidation $oxidation) : CopperMaterial{
- $block->setOxidation($oxidation);
- $block->setWaxed(false);
- return $block;
- }
-
- /**
- * @phpstan-template TBlock of CopperMaterial
- *
- * @phpstan-param TBlock $block
- * @phpstan-return TBlock
- */
- public static function decodeWaxedCopper(CopperMaterial $block, CopperOxidation $oxidation) : CopperMaterial{
- $block->setOxidation($oxidation);
- $block->setWaxed(true);
- return $block;
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeDaylightSensor(DaylightSensor $block, BlockStateReader $in) : DaylightSensor{
- return $block
- ->setOutputSignalStrength($in->readBoundedInt(BlockStateNames::REDSTONE_SIGNAL, 0, 15));
- }
-
- /**
- * @phpstan-template TDoor of Door
- * @phpstan-param TDoor $block
- * @phpstan-return TDoor
- *
- * @throws BlockStateDeserializeException
- */
- public static function decodeDoor(Door $block, BlockStateReader $in) : Door{
- //TODO: check if these need any special treatment to get the appropriate data to both halves of the door
- return $block
- ->setTop($in->readBool(BlockStateNames::UPPER_BLOCK_BIT))
- //a door facing "east" is actually facing north - thanks mojang
- ->setFacing(Facing::rotateY($in->readCardinalHorizontalFacing(), clockwise: false))
- ->setHingeRight($in->readBool(BlockStateNames::DOOR_HINGE_BIT))
- ->setOpen($in->readBool(BlockStateNames::OPEN_BIT));
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeDoublePlant(DoublePlant $block, BlockStateReader $in) : DoublePlant{
- return $block
- ->setTop($in->readBool(BlockStateNames::UPPER_BLOCK_BIT));
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeFenceGate(FenceGate $block, BlockStateReader $in) : FenceGate{
- return $block
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setInWall($in->readBool(BlockStateNames::IN_WALL_BIT))
- ->setOpen($in->readBool(BlockStateNames::OPEN_BIT));
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeFloorCoralFan(FloorCoralFan $block, BlockStateReader $in) : FloorCoralFan{
- return $block
- ->setAxis(match($in->readBoundedInt(BlockStateNames::CORAL_FAN_DIRECTION, 0, 1)){
- 0 => Axis::X,
- 1 => Axis::Z,
- default => throw new AssumptionFailedError("readBoundedInt() should have prevented this"),
- });
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeFloorSign(FloorSign $block, BlockStateReader $in) : FloorSign{
- return $block
- ->setRotation($in->readBoundedInt(BlockStateNames::GROUND_SIGN_DIRECTION, 0, 15));
- }
-
- public static function decodeItemFrame(ItemFrame $block, BlockStateReader $in) : ItemFrame{
- $in->todo(StateNames::ITEM_FRAME_PHOTO_BIT); //TODO: not sure what the point of this is
- return $block
- ->setFacing($in->readFacingDirection())
- ->setHasMap($in->readBool(StateNames::ITEM_FRAME_MAP_BIT));
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeLeaves(Leaves $block, BlockStateReader $in) : Leaves{
- return $block
- ->setNoDecay($in->readBool(StateNames::PERSISTENT_BIT))
- ->setCheckDecay($in->readBool(StateNames::UPDATE_BIT));
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeLiquid(Liquid $block, BlockStateReader $in, bool $still) : Liquid{
- $fluidHeightState = $in->readBoundedInt(BlockStateNames::LIQUID_DEPTH, 0, 15);
- return $block
- ->setDecay($fluidHeightState & 0x7)
- ->setFalling(($fluidHeightState & 0x8) !== 0)
- ->setStill($still);
- }
-
- public static function decodeFlowingLiquid(Liquid $block, BlockStateReader $in) : Liquid{
- return self::decodeLiquid($block, $in, false);
- }
-
- public static function decodeStillLiquid(Liquid $block, BlockStateReader $in) : Liquid{
- return self::decodeLiquid($block, $in, true);
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeLog(Wood $block, bool $stripped, BlockStateReader $in) : Wood{
- return $block
- ->setAxis($in->readPillarAxis())
- ->setStripped($stripped);
- }
-
- /** @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:
- 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);
- return $type !== null ? $block->setMushroomBlockType($type) : $block;
- }
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeRepeater(RedstoneRepeater $block, BlockStateReader $in) : RedstoneRepeater{
- return $block
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setDelay($in->readBoundedInt(BlockStateNames::REPEATER_DELAY, 0, 3) + 1);
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeSapling(Sapling $block, BlockStateReader $in) : Sapling{
- return $block
- ->setReady($in->readBool(BlockStateNames::AGE_BIT));
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeSimplePressurePlate(SimplePressurePlate $block, BlockStateReader $in) : SimplePressurePlate{
- //TODO: not sure what the deal is here ... seems like a mojang bug / artifact of bad implementation?
- //best to keep this separate from weighted plates anyway...
- return $block->setPressed($in->readBoundedInt(BlockStateNames::REDSTONE_SIGNAL, 0, 15) !== 0);
- }
-
- /**
- * @phpstan-template TSlab of Slab
- * @phpstan-param TSlab $block
- * @phpstan-return TSlab
- *
- * @throws BlockStateDeserializeException
- */
- public static function decodeSingleSlab(Slab $block, BlockStateReader $in) : Slab{
- return $block->setSlabType($in->readSlabPosition());
- }
-
- /**
- * @phpstan-template TSlab of Slab
- * @phpstan-param TSlab $block
- * @phpstan-return TSlab
- *
- * @throws BlockStateDeserializeException
- */
- public static function decodeDoubleSlab(Slab $block, BlockStateReader $in) : Slab{
- $in->ignored(StateNames::MC_VERTICAL_HALF);
- return $block->setSlabType(SlabType::DOUBLE);
- }
-
- /**
- * @phpstan-template TStair of Stair
- * @phpstan-param TStair $block
- * @phpstan-return TStair
- *
- * @throws BlockStateDeserializeException
- */
- public static function decodeStairs(Stair $block, BlockStateReader $in) : Stair{
- return $block
- ->setUpsideDown($in->readBool(BlockStateNames::UPSIDE_DOWN_BIT))
- ->setFacing($in->readWeirdoHorizontalFacing());
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeStem(Stem $block, BlockStateReader $in) : Stem{
- //In PM, we use Facing::UP to indicate that the stem is not attached to a pumpkin/melon, since this makes the
- //most intuitive sense (the stem is pointing at the sky). However, Bedrock uses the DOWN state for this, which
- //is absurd, and I refuse to make our API similarly absurd.
- $facing = $in->readFacingWithoutUp();
- return self::decodeCrops($block, $in)
- ->setFacing($facing === Facing::DOWN ? Facing::UP : $facing);
- }
-
- /**
- * @phpstan-template TTrapdoor of Trapdoor
- * @phpstan-param TTrapdoor $block
- * @phpstan-return TTrapdoor
- *
- * @throws BlockStateDeserializeException
- */
- public static function decodeTrapdoor(Trapdoor $block, BlockStateReader $in) : Trapdoor{
- return $block
- ->setFacing($in->read5MinusHorizontalFacing())
- ->setTop($in->readBool(BlockStateNames::UPSIDE_DOWN_BIT))
- ->setOpen($in->readBool(BlockStateNames::OPEN_BIT));
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeWall(Wall $block, BlockStateReader $in) : Wall{
- $block->setPost($in->readBool(BlockStateNames::WALL_POST_BIT));
- $block->setConnection(Facing::NORTH, $in->readWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_NORTH));
- $block->setConnection(Facing::SOUTH, $in->readWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_SOUTH));
- $block->setConnection(Facing::WEST, $in->readWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_WEST));
- $block->setConnection(Facing::EAST, $in->readWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_EAST));
-
- return $block;
- }
-
- /** @throws BlockStateDeserializeException */
- public static function decodeWallSign(WallSign $block, BlockStateReader $in) : WallSign{
- return $block
- ->setFacing($in->readHorizontalFacing());
- }
-
- public static function decodeWeightedPressurePlate(WeightedPressurePlate $block, BlockStateReader $in) : WeightedPressurePlate{
- return $block
- ->setOutputSignalStrength($in->readBoundedInt(BlockStateNames::REDSTONE_SIGNAL, 0, 15));
- }
-}
diff --git a/src/data/bedrock/block/convert/BlockStateReader.php b/src/data/bedrock/block/convert/BlockStateReader.php
index e3a02885f..adcdf9709 100644
--- a/src/data/bedrock/block/convert/BlockStateReader.php
+++ b/src/data/bedrock/block/convert/BlockStateReader.php
@@ -23,16 +23,8 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock\block\convert;
-use pocketmine\block\utils\BellAttachmentType;
-use pocketmine\block\utils\SlabType;
-use pocketmine\block\utils\WallConnectionType;
-use pocketmine\data\bedrock\block\BlockLegacyMetadata;
use pocketmine\data\bedrock\block\BlockStateData;
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
-use pocketmine\data\bedrock\block\BlockStateNames;
-use pocketmine\data\bedrock\block\BlockStateStringValues as StringValues;
-use pocketmine\math\Axis;
-use pocketmine\math\Facing;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
@@ -111,227 +103,6 @@ final class BlockStateReader{
throw $this->missingOrWrongTypeException($name, $tag);
}
- /**
- * @param int[] $mapping
- * @phpstan-param array $mapping
- * @phpstan-return int
- * @throws BlockStateDeserializeException
- */
- private function parseFacingValue(int $value, array $mapping) : int{
- $result = $mapping[$value] ?? null;
- if($result === null){
- throw new BlockStateDeserializeException("Unmapped facing value " . $value);
- }
- return $result;
- }
-
- /** @throws BlockStateDeserializeException */
- public function readFacingDirection() : int{
- return $this->parseFacingValue($this->readInt(BlockStateNames::FACING_DIRECTION), [
- 0 => Facing::DOWN,
- 1 => Facing::UP,
- 2 => Facing::NORTH,
- 3 => Facing::SOUTH,
- 4 => Facing::WEST,
- 5 => Facing::EAST
- ]);
- }
-
- /** @throws BlockStateDeserializeException */
- public function readBlockFace() : int{
- return match($raw = $this->readString(BlockStateNames::MC_BLOCK_FACE)){
- StringValues::MC_BLOCK_FACE_DOWN => Facing::DOWN,
- StringValues::MC_BLOCK_FACE_UP => Facing::UP,
- StringValues::MC_BLOCK_FACE_NORTH => Facing::NORTH,
- StringValues::MC_BLOCK_FACE_SOUTH => Facing::SOUTH,
- StringValues::MC_BLOCK_FACE_WEST => Facing::WEST,
- StringValues::MC_BLOCK_FACE_EAST => Facing::EAST,
- default => throw $this->badValueException(BlockStateNames::MC_BLOCK_FACE, $raw)
- };
- }
-
- /**
- * @return int[]
- * @phpstan-return array
- */
- public function readFacingFlags() : array{
- $result = [];
- $flags = $this->readBoundedInt(BlockStateNames::MULTI_FACE_DIRECTION_BITS, 0, 63);
- foreach([
- BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_DOWN => Facing::DOWN,
- BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_UP => Facing::UP,
- BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_NORTH => Facing::NORTH,
- BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_SOUTH => Facing::SOUTH,
- BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_WEST => Facing::WEST,
- BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_EAST => Facing::EAST
- ] as $flag => $facing){
- if(($flags & $flag) !== 0){
- $result[$facing] = $facing;
- }
- }
-
- return $result;
- }
-
- /** @throws BlockStateDeserializeException */
- public function readEndRodFacingDirection() : int{
- $result = $this->readFacingDirection();
- return Facing::axis($result) !== Axis::Y ? Facing::opposite($result) : $result;
- }
-
- /** @throws BlockStateDeserializeException */
- public function readHorizontalFacing() : int{
- return $this->parseFacingValue($this->readInt(BlockStateNames::FACING_DIRECTION), [
- 0 => Facing::NORTH, //should be illegal, but 1.13 allows it
- 1 => Facing::NORTH, //also should be illegal
- 2 => Facing::NORTH,
- 3 => Facing::SOUTH,
- 4 => Facing::WEST,
- 5 => Facing::EAST
- ]);
- }
-
- /** @throws BlockStateDeserializeException */
- public function readWeirdoHorizontalFacing() : int{
- return $this->parseFacingValue($this->readInt(BlockStateNames::WEIRDO_DIRECTION), [
- 0 => Facing::EAST,
- 1 => Facing::WEST,
- 2 => Facing::SOUTH,
- 3 => Facing::NORTH
- ]);
- }
-
- /** @throws BlockStateDeserializeException */
- public function readLegacyHorizontalFacing() : int{
- return $this->parseFacingValue($this->readInt(BlockStateNames::DIRECTION), [
- 0 => Facing::SOUTH,
- 1 => Facing::WEST,
- 2 => Facing::NORTH,
- 3 => Facing::EAST
- ]);
- }
-
- /**
- * This is for trapdoors, because Mojang botched the conversion in 1.13
- * @throws BlockStateDeserializeException
- */
- public function read5MinusHorizontalFacing() : int{
- return $this->parseFacingValue($this->readInt(BlockStateNames::DIRECTION), [
- 0 => Facing::EAST,
- 1 => Facing::WEST,
- 2 => Facing::SOUTH,
- 3 => Facing::NORTH
- ]);
- }
-
- /**
- * Used by pumpkins as of 1.20.0.23 beta
- * @throws BlockStateDeserializeException
- */
- public function readCardinalHorizontalFacing() : int{
- return match($raw = $this->readString(BlockStateNames::MC_CARDINAL_DIRECTION)){
- StringValues::MC_CARDINAL_DIRECTION_NORTH => Facing::NORTH,
- StringValues::MC_CARDINAL_DIRECTION_SOUTH => Facing::SOUTH,
- StringValues::MC_CARDINAL_DIRECTION_WEST => Facing::WEST,
- StringValues::MC_CARDINAL_DIRECTION_EAST => Facing::EAST,
- default => throw $this->badValueException(BlockStateNames::MC_CARDINAL_DIRECTION, $raw)
- };
- }
-
- /** @throws BlockStateDeserializeException */
- public function readCoralFacing() : int{
- return $this->parseFacingValue($this->readInt(BlockStateNames::CORAL_DIRECTION), [
- 0 => Facing::WEST,
- 1 => Facing::EAST,
- 2 => Facing::NORTH,
- 3 => Facing::SOUTH
- ]);
- }
-
- /** @throws BlockStateDeserializeException */
- public function readFacingWithoutDown() : int{
- $result = $this->readFacingDirection();
- if($result === Facing::DOWN){ //shouldn't be legal, but 1.13 allows it
- $result = Facing::UP;
- }
- return $result;
- }
-
- public function readFacingWithoutUp() : int{
- $result = $this->readFacingDirection();
- if($result === Facing::UP){
- $result = Facing::DOWN; //shouldn't be legal, but 1.13 allows it
- }
- return $result;
- }
-
- /**
- * @phpstan-return Axis::*
- * @throws BlockStateDeserializeException
- */
- public function readPillarAxis() : int{
- $rawValue = $this->readString(BlockStateNames::PILLAR_AXIS);
- $value = [
- StringValues::PILLAR_AXIS_X => Axis::X,
- StringValues::PILLAR_AXIS_Y => Axis::Y,
- StringValues::PILLAR_AXIS_Z => Axis::Z
- ][$rawValue] ?? null;
- if($value === null){
- throw $this->badValueException(BlockStateNames::PILLAR_AXIS, $rawValue, "Invalid axis value");
- }
- return $value;
- }
-
- /** @throws BlockStateDeserializeException */
- public function readSlabPosition() : SlabType{
- return match($rawValue = $this->readString(BlockStateNames::MC_VERTICAL_HALF)){
- StringValues::MC_VERTICAL_HALF_BOTTOM => SlabType::BOTTOM,
- StringValues::MC_VERTICAL_HALF_TOP => SlabType::TOP,
- default => throw $this->badValueException(BlockStateNames::MC_VERTICAL_HALF, $rawValue, "Invalid slab position"),
- };
- }
-
- /**
- * @phpstan-return Facing::UP|Facing::NORTH|Facing::SOUTH|Facing::WEST|Facing::EAST
- * @throws BlockStateDeserializeException
- */
- public function readTorchFacing() : int{
- //TODO: horizontal directions are flipped (MCPE bug: https://bugs.mojang.com/browse/MCPE-152036)
- return match($rawValue = $this->readString(BlockStateNames::TORCH_FACING_DIRECTION)){
- StringValues::TORCH_FACING_DIRECTION_EAST => Facing::WEST,
- StringValues::TORCH_FACING_DIRECTION_NORTH => Facing::SOUTH,
- StringValues::TORCH_FACING_DIRECTION_SOUTH => Facing::NORTH,
- StringValues::TORCH_FACING_DIRECTION_TOP => Facing::UP,
- StringValues::TORCH_FACING_DIRECTION_UNKNOWN => Facing::UP, //should be illegal, but 1.13 allows it
- StringValues::TORCH_FACING_DIRECTION_WEST => Facing::EAST,
- default => throw $this->badValueException(BlockStateNames::TORCH_FACING_DIRECTION, $rawValue, "Invalid torch facing"),
- };
- }
-
- /** @throws BlockStateDeserializeException */
- public function readBellAttachmentType() : BellAttachmentType{
- return match($type = $this->readString(BlockStateNames::ATTACHMENT)){
- StringValues::ATTACHMENT_HANGING => BellAttachmentType::CEILING,
- StringValues::ATTACHMENT_STANDING => BellAttachmentType::FLOOR,
- StringValues::ATTACHMENT_SIDE => BellAttachmentType::ONE_WALL,
- StringValues::ATTACHMENT_MULTIPLE => BellAttachmentType::TWO_WALLS,
- default => throw $this->badValueException(BlockStateNames::ATTACHMENT, $type),
- };
- }
-
- /** @throws BlockStateDeserializeException */
- public function readWallConnectionType(string $name) : ?WallConnectionType{
- return match($type = $this->readString($name)){
- //TODO: this looks a bit confusing due to use of EAST, but the values are the same for all connections
- //we need to find a better way to auto-generate the constant names when they are reused
- //for now, using these constants is better than nothing since it still gives static analysability
- StringValues::WALL_CONNECTION_TYPE_EAST_NONE => null,
- StringValues::WALL_CONNECTION_TYPE_EAST_SHORT => WallConnectionType::SHORT,
- StringValues::WALL_CONNECTION_TYPE_EAST_TALL => WallConnectionType::TALL,
- default => throw $this->badValueException($name, $type),
- };
- }
-
/**
* Explicitly mark a property as unused, so it doesn't get flagged as an error when debug mode is enabled
*/
diff --git a/src/data/bedrock/block/convert/BlockStateSerializerHelper.php b/src/data/bedrock/block/convert/BlockStateSerializerHelper.php
deleted file mode 100644
index a25044153..000000000
--- a/src/data/bedrock/block/convert/BlockStateSerializerHelper.php
+++ /dev/null
@@ -1,231 +0,0 @@
-writeFacingDirection($block->getFacing())
- ->writeBool(BlockStateNames::BUTTON_PRESSED_BIT, $block->isPressed());
- }
-
- public static function encodeCandle(Candle $block, Writer $out) : Writer{
- return $out
- ->writeBool(StateNames::LIT, $block->isLit())
- ->writeInt(StateNames::CANDLES, $block->getCount() - 1);
- }
-
- public static function encodeChemistryTable(ChemistryTable $block, Writer $out) : Writer{
- return $out
- ->writeLegacyHorizontalFacing(Facing::opposite($block->getFacing()));
- }
-
- public static function encodeCrops(Crops $block, Writer $out) : Writer{
- return $out->writeInt(BlockStateNames::GROWTH, $block->getAge());
- }
-
- public static function encodeTorch(Torch $block, Writer $out) : Writer{
- return $out
- ->writeTorchFacing($block->getFacing());
- }
-
- public static function encodeCauldron(string $liquid, int $fillLevel) : Writer{
- return Writer::create(Ids::CAULDRON)
- ->writeString(BlockStateNames::CAULDRON_LIQUID, $liquid)
- ->writeInt(BlockStateNames::FILL_LEVEL, $fillLevel);
- }
-
- public static function selectCopperId(CopperOxidation $oxidation, string $noneId, string $exposedId, string $weatheredId, string $oxidizedId) : string{
- return match($oxidation){
- CopperOxidation::NONE => $noneId,
- CopperOxidation::EXPOSED => $exposedId,
- CopperOxidation::WEATHERED => $weatheredId,
- CopperOxidation::OXIDIZED => $oxidizedId,
- };
- }
-
- public static function encodeDoor(Door $block, Writer $out) : Writer{
- return $out
- ->writeBool(BlockStateNames::UPPER_BLOCK_BIT, $block->isTop())
- //a door facing north is encoded as "east"
- ->writeCardinalHorizontalFacing(Facing::rotateY($block->getFacing(), clockwise: true))
- ->writeBool(BlockStateNames::DOOR_HINGE_BIT, $block->isHingeRight())
- ->writeBool(BlockStateNames::OPEN_BIT, $block->isOpen());
- }
-
- public static function encodeDoublePlant(DoublePlant $block, Writer $out) : Writer{
- return $out
- ->writeBool(BlockStateNames::UPPER_BLOCK_BIT, $block->isTop());
- }
-
- public static function encodeFenceGate(FenceGate $block, Writer $out) : Writer{
- return $out
- ->writeCardinalHorizontalFacing($block->getFacing())
- ->writeBool(BlockStateNames::IN_WALL_BIT, $block->isInWall())
- ->writeBool(BlockStateNames::OPEN_BIT, $block->isOpen());
- }
-
- public static function encodeFloorSign(FloorSign $block, Writer $out) : Writer{
- return $out
- ->writeInt(BlockStateNames::GROUND_SIGN_DIRECTION, $block->getRotation());
- }
-
- public static function encodeFurnace(Furnace $block, string $unlitId, string $litId) : Writer{
- return Writer::create($block->isLit() ? $litId : $unlitId)
- ->writeCardinalHorizontalFacing($block->getFacing());
- }
-
- public static function encodeItemFrame(ItemFrame $block, string $id) : Writer{
- return Writer::create($id)
- ->writeBool(StateNames::ITEM_FRAME_MAP_BIT, $block->hasMap())
- ->writeBool(StateNames::ITEM_FRAME_PHOTO_BIT, false)
- ->writeFacingDirection($block->getFacing());
- }
-
- public static function encodeLeaves(Leaves $block, Writer $out) : Writer{
- return $out
- ->writeBool(BlockStateNames::PERSISTENT_BIT, $block->isNoDecay())
- ->writeBool(BlockStateNames::UPDATE_BIT, $block->isCheckDecay());
- }
-
- public static function encodeLiquid(Liquid $block, string $stillId, string $flowingId) : Writer{
- return Writer::create($block->isStill() ? $stillId : $flowingId)
- ->writeInt(BlockStateNames::LIQUID_DEPTH, $block->getDecay() | ($block->isFalling() ? 0x8 : 0));
- }
-
- public static function encodeLog(Wood $block, string $unstrippedId, string $strippedId) : Writer{
- $out = $block->isStripped() ?
- Writer::create($strippedId) :
- Writer::create($unstrippedId);
- return $out
- ->writePillarAxis($block->getAxis());
- }
-
- public static function encodeMushroomBlock(RedMushroomBlock $block, Writer $out) : Writer{
- return $out
- ->writeInt(BlockStateNames::HUGE_MUSHROOM_BITS, MushroomBlockTypeIdMap::getInstance()->toId($block->getMushroomBlockType()));
- }
-
- 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 encodeSapling(Sapling $block, Writer $out) : Writer{
- return $out
- ->writeBool(BlockStateNames::AGE_BIT, $block->isReady());
- }
-
- public static function encodeSimplePressurePlate(SimplePressurePlate $block, Writer $out) : Writer{
- //TODO: not sure what the deal is here ... seems like a mojang bug / artifact of bad implementation?
- //best to keep this separate from weighted plates anyway...
- return $out
- ->writeInt(BlockStateNames::REDSTONE_SIGNAL, $block->isPressed() ? 15 : 0);
- }
-
- private static function encodeSingleSlab(Slab $block, string $id) : Writer{
- return Writer::create($id)
- ->writeSlabPosition($block->getSlabType());
- }
-
- private static function encodeDoubleSlab(Slab $block, string $id) : Writer{
- return Writer::create($id)
- //this is (intentionally) also written for double slabs (as zero) to maintain bug parity with MCPE
- ->writeSlabPosition(SlabType::BOTTOM);
- }
-
- public static function encodeSlab(Slab $block, string $singleId, string $doubleId) : Writer{
- return $block->getSlabType() === SlabType::DOUBLE ?
- self::encodeDoubleSlab($block, $doubleId) :
- self::encodeSingleSlab($block, $singleId);
- }
-
- public static function encodeStairs(Stair $block, Writer $out) : Writer{
- return $out
- ->writeBool(BlockStateNames::UPSIDE_DOWN_BIT, $block->isUpsideDown())
- ->writeWeirdoHorizontalFacing($block->getFacing());
- }
-
- public static function encodeStem(Stem $block, Writer $out) : Writer{
- //In PM, we use Facing::UP to indicate that the stem is not attached to a pumpkin/melon, since this makes the
- //most intuitive sense (the stem is pointing at the sky). However, Bedrock uses the DOWN state for this, which
- //is absurd, and I refuse to make our API similarly absurd.
- $facing = $block->getFacing();
- return self::encodeCrops($block, $out)
- ->writeFacingWithoutUp($facing === Facing::UP ? Facing::DOWN : $facing);
- }
-
- public static function encodeTrapdoor(Trapdoor $block, Writer $out) : Writer{
- return $out
- ->write5MinusHorizontalFacing($block->getFacing())
- ->writeBool(BlockStateNames::UPSIDE_DOWN_BIT, $block->isTop())
- ->writeBool(BlockStateNames::OPEN_BIT, $block->isOpen());
- }
-
- public static function encodeWall(Wall $block, Writer $out) : Writer{
- return $out
- ->writeBool(BlockStateNames::WALL_POST_BIT, $block->isPost())
- ->writeWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_EAST, $block->getConnection(Facing::EAST))
- ->writeWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_NORTH, $block->getConnection(Facing::NORTH))
- ->writeWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_SOUTH, $block->getConnection(Facing::SOUTH))
- ->writeWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_WEST, $block->getConnection(Facing::WEST));
- }
-
- public static function encodeWallSign(WallSign $block, Writer $out) : Writer{
- return $out
- ->writeHorizontalFacing($block->getFacing());
- }
-}
diff --git a/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php b/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php
index ed45a47d3..18d549774 100644
--- a/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php
+++ b/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php
@@ -23,48 +23,14 @@ 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\Opaque;
-use pocketmine\block\PinkPetals;
-use pocketmine\block\PitcherCrop;
use pocketmine\block\RuntimeBlockStateRegistry;
-use pocketmine\block\Slab;
-use pocketmine\block\Stair;
-use pocketmine\block\SweetBerryBush;
-use pocketmine\block\utils\BrewingStandSlot;
-use pocketmine\block\utils\ChiseledBookshelfSlot;
-use pocketmine\block\utils\CopperMaterial;
-use pocketmine\block\utils\CopperOxidation;
-use pocketmine\block\utils\CoralType;
-use pocketmine\block\utils\DirtType;
-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;
use pocketmine\data\bedrock\block\BlockStateData;
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
use pocketmine\data\bedrock\block\BlockStateDeserializer;
-use pocketmine\data\bedrock\block\BlockStateNames as StateNames;
-use pocketmine\data\bedrock\block\BlockStateStringValues as StringValues;
-use pocketmine\data\bedrock\block\BlockTypeNames as Ids;
-use pocketmine\data\bedrock\block\convert\BlockStateDeserializerHelper as Helper;
use pocketmine\data\bedrock\block\convert\BlockStateReader as Reader;
-use pocketmine\math\Axis;
-use pocketmine\math\Facing;
-use pocketmine\utils\Utils;
use function array_key_exists;
use function count;
-use function min;
final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
@@ -80,21 +46,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
*/
private array $simpleCache = [];
- public function __construct(){
- $this->registerCandleDeserializers();
- $this->registerFlatColorBlockDeserializers();
- $this->registerFlatCoralDeserializers();
- $this->registerCauldronDeserializers();
- $this->registerFlatWoodBlockDeserializers();
- $this->registerLeavesDeserializers();
- $this->registerSaplingDeserializers();
- $this->registerLightDeserializers();
- $this->registerMobHeadDeserializers();
- $this->registerCopperDeserializers();
- $this->registerSimpleDeserializers();
- $this->registerDeserializers();
- }
-
public function deserialize(BlockStateData $stateData) : int{
if(count($stateData->getStates()) === 0){
//if a block has zero properties, we can keep a map of string ID -> internal blockstate ID
@@ -131,1747 +82,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
return $this->deserializeFuncs[$id] ?? null;
}
- /** @phpstan-param \Closure() : Block $getBlock */
- public function mapSimple(string $id, \Closure $getBlock) : void{
- $this->map($id, $getBlock);
- }
-
- /**
- * @phpstan-param \Closure(Reader) : Slab $getBlock
- */
- public function mapSlab(string $singleId, string $doubleId, \Closure $getBlock) : void{
- $this->map($singleId, fn(Reader $in) => Helper::decodeSingleSlab($getBlock($in), $in));
- $this->map($doubleId, fn(Reader $in) => Helper::decodeDoubleSlab($getBlock($in), $in));
- }
-
- /**
- * @phpstan-param \Closure() : Stair $getBlock
- */
- public function mapStairs(string $id, \Closure $getBlock) : void{
- $this->map($id, fn(Reader $in) : Stair => Helper::decodeStairs($getBlock(), $in));
- }
-
- /** @phpstan-param \Closure() : Wood $getBlock */
- public function mapLog(string $unstrippedId, string $strippedId, \Closure $getBlock) : void{
- $this->map($unstrippedId, fn(Reader $in) => Helper::decodeLog($getBlock(), false, $in));
- $this->map($strippedId, fn(Reader $in) => Helper::decodeLog($getBlock(), true, $in));
- }
-
- private function registerCandleDeserializers() : void{
- $this->map(Ids::CANDLE, fn(Reader $in) => Helper::decodeCandle(Blocks::CANDLE(), $in));
- foreach([
- Ids::BLACK_CANDLE => DyeColor::BLACK,
- Ids::BLUE_CANDLE => DyeColor::BLUE,
- Ids::BROWN_CANDLE => DyeColor::BROWN,
- Ids::CYAN_CANDLE => DyeColor::CYAN,
- Ids::GRAY_CANDLE => DyeColor::GRAY,
- Ids::GREEN_CANDLE => DyeColor::GREEN,
- Ids::LIGHT_BLUE_CANDLE => DyeColor::LIGHT_BLUE,
- Ids::LIGHT_GRAY_CANDLE => DyeColor::LIGHT_GRAY,
- Ids::LIME_CANDLE => DyeColor::LIME,
- Ids::MAGENTA_CANDLE => DyeColor::MAGENTA,
- Ids::ORANGE_CANDLE => DyeColor::ORANGE,
- Ids::PINK_CANDLE => DyeColor::PINK,
- Ids::PURPLE_CANDLE => DyeColor::PURPLE,
- Ids::RED_CANDLE => DyeColor::RED,
- Ids::WHITE_CANDLE => DyeColor::WHITE,
- Ids::YELLOW_CANDLE => DyeColor::YELLOW,
- ] as $id => $color){
- $this->map($id, fn(Reader $in) => Helper::decodeCandle(Blocks::DYED_CANDLE()->setColor($color), $in));
- }
-
- $this->map(Ids::CANDLE_CAKE, fn(Reader $in) => Blocks::CAKE_WITH_CANDLE()->setLit($in->readBool(StateNames::LIT)));
- foreach([
- Ids::BLACK_CANDLE_CAKE => DyeColor::BLACK,
- Ids::BLUE_CANDLE_CAKE => DyeColor::BLUE,
- Ids::BROWN_CANDLE_CAKE => DyeColor::BROWN,
- Ids::CYAN_CANDLE_CAKE => DyeColor::CYAN,
- Ids::GRAY_CANDLE_CAKE => DyeColor::GRAY,
- Ids::GREEN_CANDLE_CAKE => DyeColor::GREEN,
- Ids::LIGHT_BLUE_CANDLE_CAKE => DyeColor::LIGHT_BLUE,
- Ids::LIGHT_GRAY_CANDLE_CAKE => DyeColor::LIGHT_GRAY,
- Ids::LIME_CANDLE_CAKE => DyeColor::LIME,
- Ids::MAGENTA_CANDLE_CAKE => DyeColor::MAGENTA,
- Ids::ORANGE_CANDLE_CAKE => DyeColor::ORANGE,
- Ids::PINK_CANDLE_CAKE => DyeColor::PINK,
- Ids::PURPLE_CANDLE_CAKE => DyeColor::PURPLE,
- Ids::RED_CANDLE_CAKE => DyeColor::RED,
- Ids::WHITE_CANDLE_CAKE => DyeColor::WHITE,
- Ids::YELLOW_CANDLE_CAKE => DyeColor::YELLOW,
- ] as $id => $color){
- $this->map($id, fn(Reader $in) => Blocks::CAKE_WITH_DYED_CANDLE()
- ->setColor($color)
- ->setLit($in->readBool(StateNames::LIT))
- );
- }
- }
-
- private function registerFlatColorBlockDeserializers() : void{
- foreach([
- Ids::HARD_BLACK_STAINED_GLASS => DyeColor::BLACK,
- Ids::HARD_BLUE_STAINED_GLASS => DyeColor::BLUE,
- Ids::HARD_BROWN_STAINED_GLASS => DyeColor::BROWN,
- Ids::HARD_CYAN_STAINED_GLASS => DyeColor::CYAN,
- Ids::HARD_GRAY_STAINED_GLASS => DyeColor::GRAY,
- Ids::HARD_GREEN_STAINED_GLASS => DyeColor::GREEN,
- Ids::HARD_LIGHT_BLUE_STAINED_GLASS => DyeColor::LIGHT_BLUE,
- Ids::HARD_LIGHT_GRAY_STAINED_GLASS => DyeColor::LIGHT_GRAY,
- Ids::HARD_LIME_STAINED_GLASS => DyeColor::LIME,
- Ids::HARD_MAGENTA_STAINED_GLASS => DyeColor::MAGENTA,
- Ids::HARD_ORANGE_STAINED_GLASS => DyeColor::ORANGE,
- Ids::HARD_PINK_STAINED_GLASS => DyeColor::PINK,
- Ids::HARD_PURPLE_STAINED_GLASS => DyeColor::PURPLE,
- Ids::HARD_RED_STAINED_GLASS => DyeColor::RED,
- Ids::HARD_WHITE_STAINED_GLASS => DyeColor::WHITE,
- Ids::HARD_YELLOW_STAINED_GLASS => DyeColor::YELLOW,
- ] as $id => $color){
- $this->map($id, fn(Reader $in) => Blocks::STAINED_HARDENED_GLASS()->setColor($color));
- }
-
- foreach([
- Ids::HARD_BLACK_STAINED_GLASS_PANE => DyeColor::BLACK,
- Ids::HARD_BLUE_STAINED_GLASS_PANE => DyeColor::BLUE,
- Ids::HARD_BROWN_STAINED_GLASS_PANE => DyeColor::BROWN,
- Ids::HARD_CYAN_STAINED_GLASS_PANE => DyeColor::CYAN,
- Ids::HARD_GRAY_STAINED_GLASS_PANE => DyeColor::GRAY,
- Ids::HARD_GREEN_STAINED_GLASS_PANE => DyeColor::GREEN,
- Ids::HARD_LIGHT_BLUE_STAINED_GLASS_PANE => DyeColor::LIGHT_BLUE,
- Ids::HARD_LIGHT_GRAY_STAINED_GLASS_PANE => DyeColor::LIGHT_GRAY,
- Ids::HARD_LIME_STAINED_GLASS_PANE => DyeColor::LIME,
- Ids::HARD_MAGENTA_STAINED_GLASS_PANE => DyeColor::MAGENTA,
- Ids::HARD_ORANGE_STAINED_GLASS_PANE => DyeColor::ORANGE,
- Ids::HARD_PINK_STAINED_GLASS_PANE => DyeColor::PINK,
- Ids::HARD_PURPLE_STAINED_GLASS_PANE => DyeColor::PURPLE,
- Ids::HARD_RED_STAINED_GLASS_PANE => DyeColor::RED,
- Ids::HARD_WHITE_STAINED_GLASS_PANE => DyeColor::WHITE,
- Ids::HARD_YELLOW_STAINED_GLASS_PANE => DyeColor::YELLOW,
- ] as $id => $color){
- $this->map($id, fn(Reader $in) => Blocks::STAINED_HARDENED_GLASS_PANE()->setColor($color));
- }
-
- foreach([
- Ids::BLACK_GLAZED_TERRACOTTA => DyeColor::BLACK,
- Ids::BLUE_GLAZED_TERRACOTTA => DyeColor::BLUE,
- Ids::BROWN_GLAZED_TERRACOTTA => DyeColor::BROWN,
- Ids::CYAN_GLAZED_TERRACOTTA => DyeColor::CYAN,
- Ids::GRAY_GLAZED_TERRACOTTA => DyeColor::GRAY,
- Ids::GREEN_GLAZED_TERRACOTTA => DyeColor::GREEN,
- Ids::LIGHT_BLUE_GLAZED_TERRACOTTA => DyeColor::LIGHT_BLUE,
- Ids::SILVER_GLAZED_TERRACOTTA => DyeColor::LIGHT_GRAY,
- Ids::LIME_GLAZED_TERRACOTTA => DyeColor::LIME,
- Ids::MAGENTA_GLAZED_TERRACOTTA => DyeColor::MAGENTA,
- Ids::ORANGE_GLAZED_TERRACOTTA => DyeColor::ORANGE,
- Ids::PINK_GLAZED_TERRACOTTA => DyeColor::PINK,
- Ids::PURPLE_GLAZED_TERRACOTTA => DyeColor::PURPLE,
- Ids::RED_GLAZED_TERRACOTTA => DyeColor::RED,
- Ids::WHITE_GLAZED_TERRACOTTA => DyeColor::WHITE,
- Ids::YELLOW_GLAZED_TERRACOTTA => DyeColor::YELLOW,
- ] as $id => $color){
- $this->map($id, fn(Reader $in) => Blocks::GLAZED_TERRACOTTA()
- ->setColor($color)
- ->setFacing($in->readHorizontalFacing())
- );
- }
-
- foreach([
- Ids::BLACK_WOOL => DyeColor::BLACK,
- Ids::BLUE_WOOL => DyeColor::BLUE,
- Ids::BROWN_WOOL => DyeColor::BROWN,
- Ids::CYAN_WOOL => DyeColor::CYAN,
- Ids::GRAY_WOOL => DyeColor::GRAY,
- Ids::GREEN_WOOL => DyeColor::GREEN,
- Ids::LIGHT_BLUE_WOOL => DyeColor::LIGHT_BLUE,
- Ids::LIGHT_GRAY_WOOL => DyeColor::LIGHT_GRAY,
- Ids::LIME_WOOL => DyeColor::LIME,
- Ids::MAGENTA_WOOL => DyeColor::MAGENTA,
- Ids::ORANGE_WOOL => DyeColor::ORANGE,
- Ids::PINK_WOOL => DyeColor::PINK,
- Ids::PURPLE_WOOL => DyeColor::PURPLE,
- Ids::RED_WOOL => DyeColor::RED,
- Ids::WHITE_WOOL => DyeColor::WHITE,
- Ids::YELLOW_WOOL => DyeColor::YELLOW,
- ] as $id => $color){
- $this->mapSimple($id, fn() => Blocks::WOOL()->setColor($color));
- }
-
- foreach([
- Ids::BLACK_CARPET => DyeColor::BLACK,
- Ids::BLUE_CARPET => DyeColor::BLUE,
- Ids::BROWN_CARPET => DyeColor::BROWN,
- Ids::CYAN_CARPET => DyeColor::CYAN,
- Ids::GRAY_CARPET => DyeColor::GRAY,
- Ids::GREEN_CARPET => DyeColor::GREEN,
- Ids::LIGHT_BLUE_CARPET => DyeColor::LIGHT_BLUE,
- Ids::LIGHT_GRAY_CARPET => DyeColor::LIGHT_GRAY,
- Ids::LIME_CARPET => DyeColor::LIME,
- Ids::MAGENTA_CARPET => DyeColor::MAGENTA,
- Ids::ORANGE_CARPET => DyeColor::ORANGE,
- Ids::PINK_CARPET => DyeColor::PINK,
- Ids::PURPLE_CARPET => DyeColor::PURPLE,
- Ids::RED_CARPET => DyeColor::RED,
- Ids::WHITE_CARPET => DyeColor::WHITE,
- Ids::YELLOW_CARPET => DyeColor::YELLOW,
- ] as $id => $color){
- $this->mapSimple($id, fn() => Blocks::CARPET()->setColor($color));
- }
-
- foreach([
- Ids::BLACK_SHULKER_BOX => DyeColor::BLACK,
- Ids::BLUE_SHULKER_BOX => DyeColor::BLUE,
- Ids::BROWN_SHULKER_BOX => DyeColor::BROWN,
- Ids::CYAN_SHULKER_BOX => DyeColor::CYAN,
- Ids::GRAY_SHULKER_BOX => DyeColor::GRAY,
- Ids::GREEN_SHULKER_BOX => DyeColor::GREEN,
- Ids::LIGHT_BLUE_SHULKER_BOX => DyeColor::LIGHT_BLUE,
- Ids::LIGHT_GRAY_SHULKER_BOX => DyeColor::LIGHT_GRAY,
- Ids::LIME_SHULKER_BOX => DyeColor::LIME,
- Ids::MAGENTA_SHULKER_BOX => DyeColor::MAGENTA,
- Ids::ORANGE_SHULKER_BOX => DyeColor::ORANGE,
- Ids::PINK_SHULKER_BOX => DyeColor::PINK,
- Ids::PURPLE_SHULKER_BOX => DyeColor::PURPLE,
- Ids::RED_SHULKER_BOX => DyeColor::RED,
- Ids::WHITE_SHULKER_BOX => DyeColor::WHITE,
- Ids::YELLOW_SHULKER_BOX => DyeColor::YELLOW,
- ] as $id => $color){
- $this->mapSimple($id, fn() => Blocks::DYED_SHULKER_BOX()->setColor($color));
- }
-
- foreach([
- Ids::BLACK_CONCRETE => DyeColor::BLACK,
- Ids::BLUE_CONCRETE => DyeColor::BLUE,
- Ids::BROWN_CONCRETE => DyeColor::BROWN,
- Ids::CYAN_CONCRETE => DyeColor::CYAN,
- Ids::GRAY_CONCRETE => DyeColor::GRAY,
- Ids::GREEN_CONCRETE => DyeColor::GREEN,
- Ids::LIGHT_BLUE_CONCRETE => DyeColor::LIGHT_BLUE,
- Ids::LIGHT_GRAY_CONCRETE => DyeColor::LIGHT_GRAY,
- Ids::LIME_CONCRETE => DyeColor::LIME,
- Ids::MAGENTA_CONCRETE => DyeColor::MAGENTA,
- Ids::ORANGE_CONCRETE => DyeColor::ORANGE,
- Ids::PINK_CONCRETE => DyeColor::PINK,
- Ids::PURPLE_CONCRETE => DyeColor::PURPLE,
- Ids::RED_CONCRETE => DyeColor::RED,
- Ids::WHITE_CONCRETE => DyeColor::WHITE,
- Ids::YELLOW_CONCRETE => DyeColor::YELLOW,
- ] as $id => $color){
- $this->mapSimple($id, fn() => Blocks::CONCRETE()->setColor($color));
- }
-
- foreach([
- Ids::BLACK_CONCRETE_POWDER => DyeColor::BLACK,
- Ids::BLUE_CONCRETE_POWDER => DyeColor::BLUE,
- Ids::BROWN_CONCRETE_POWDER => DyeColor::BROWN,
- Ids::CYAN_CONCRETE_POWDER => DyeColor::CYAN,
- Ids::GRAY_CONCRETE_POWDER => DyeColor::GRAY,
- Ids::GREEN_CONCRETE_POWDER => DyeColor::GREEN,
- Ids::LIGHT_BLUE_CONCRETE_POWDER => DyeColor::LIGHT_BLUE,
- Ids::LIGHT_GRAY_CONCRETE_POWDER => DyeColor::LIGHT_GRAY,
- Ids::LIME_CONCRETE_POWDER => DyeColor::LIME,
- Ids::MAGENTA_CONCRETE_POWDER => DyeColor::MAGENTA,
- Ids::ORANGE_CONCRETE_POWDER => DyeColor::ORANGE,
- Ids::PINK_CONCRETE_POWDER => DyeColor::PINK,
- Ids::PURPLE_CONCRETE_POWDER => DyeColor::PURPLE,
- Ids::RED_CONCRETE_POWDER => DyeColor::RED,
- Ids::WHITE_CONCRETE_POWDER => DyeColor::WHITE,
- Ids::YELLOW_CONCRETE_POWDER => DyeColor::YELLOW,
- ] as $id => $color){
- $this->mapSimple($id, fn() => Blocks::CONCRETE_POWDER()->setColor($color));
- }
-
- foreach([
- Ids::BLACK_TERRACOTTA => DyeColor::BLACK,
- Ids::BLUE_TERRACOTTA => DyeColor::BLUE,
- Ids::BROWN_TERRACOTTA => DyeColor::BROWN,
- Ids::CYAN_TERRACOTTA => DyeColor::CYAN,
- Ids::GRAY_TERRACOTTA => DyeColor::GRAY,
- Ids::GREEN_TERRACOTTA => DyeColor::GREEN,
- Ids::LIGHT_BLUE_TERRACOTTA => DyeColor::LIGHT_BLUE,
- Ids::LIGHT_GRAY_TERRACOTTA => DyeColor::LIGHT_GRAY,
- Ids::LIME_TERRACOTTA => DyeColor::LIME,
- Ids::MAGENTA_TERRACOTTA => DyeColor::MAGENTA,
- Ids::ORANGE_TERRACOTTA => DyeColor::ORANGE,
- Ids::PINK_TERRACOTTA => DyeColor::PINK,
- Ids::PURPLE_TERRACOTTA => DyeColor::PURPLE,
- Ids::RED_TERRACOTTA => DyeColor::RED,
- Ids::WHITE_TERRACOTTA => DyeColor::WHITE,
- Ids::YELLOW_TERRACOTTA => DyeColor::YELLOW,
- ] as $id => $color){
- $this->mapSimple($id, fn() => Blocks::STAINED_CLAY()->setColor($color));
- }
-
- foreach([
- Ids::BLACK_STAINED_GLASS => DyeColor::BLACK,
- Ids::BLUE_STAINED_GLASS => DyeColor::BLUE,
- Ids::BROWN_STAINED_GLASS => DyeColor::BROWN,
- Ids::CYAN_STAINED_GLASS => DyeColor::CYAN,
- Ids::GRAY_STAINED_GLASS => DyeColor::GRAY,
- Ids::GREEN_STAINED_GLASS => DyeColor::GREEN,
- Ids::LIGHT_BLUE_STAINED_GLASS => DyeColor::LIGHT_BLUE,
- Ids::LIGHT_GRAY_STAINED_GLASS => DyeColor::LIGHT_GRAY,
- Ids::LIME_STAINED_GLASS => DyeColor::LIME,
- Ids::MAGENTA_STAINED_GLASS => DyeColor::MAGENTA,
- Ids::ORANGE_STAINED_GLASS => DyeColor::ORANGE,
- Ids::PINK_STAINED_GLASS => DyeColor::PINK,
- Ids::PURPLE_STAINED_GLASS => DyeColor::PURPLE,
- Ids::RED_STAINED_GLASS => DyeColor::RED,
- Ids::WHITE_STAINED_GLASS => DyeColor::WHITE,
- Ids::YELLOW_STAINED_GLASS => DyeColor::YELLOW,
- ] as $id => $color){
- $this->mapSimple($id, fn() => Blocks::STAINED_GLASS()->setColor($color));
- }
-
- foreach([
- Ids::BLACK_STAINED_GLASS_PANE => DyeColor::BLACK,
- Ids::BLUE_STAINED_GLASS_PANE => DyeColor::BLUE,
- Ids::BROWN_STAINED_GLASS_PANE => DyeColor::BROWN,
- Ids::CYAN_STAINED_GLASS_PANE => DyeColor::CYAN,
- Ids::GRAY_STAINED_GLASS_PANE => DyeColor::GRAY,
- Ids::GREEN_STAINED_GLASS_PANE => DyeColor::GREEN,
- Ids::LIGHT_BLUE_STAINED_GLASS_PANE => DyeColor::LIGHT_BLUE,
- Ids::LIGHT_GRAY_STAINED_GLASS_PANE => DyeColor::LIGHT_GRAY,
- Ids::LIME_STAINED_GLASS_PANE => DyeColor::LIME,
- Ids::MAGENTA_STAINED_GLASS_PANE => DyeColor::MAGENTA,
- Ids::ORANGE_STAINED_GLASS_PANE => DyeColor::ORANGE,
- Ids::PINK_STAINED_GLASS_PANE => DyeColor::PINK,
- Ids::PURPLE_STAINED_GLASS_PANE => DyeColor::PURPLE,
- Ids::RED_STAINED_GLASS_PANE => DyeColor::RED,
- Ids::WHITE_STAINED_GLASS_PANE => DyeColor::WHITE,
- Ids::YELLOW_STAINED_GLASS_PANE => DyeColor::YELLOW,
- ] as $id => $color){
- $this->mapSimple($id, fn() => Blocks::STAINED_GLASS_PANE()->setColor($color));
- }
- }
-
- private function registerFlatCoralDeserializers() : void{
- foreach([
- Ids::BRAIN_CORAL => CoralType::BRAIN,
- Ids::BUBBLE_CORAL => CoralType::BUBBLE,
- Ids::FIRE_CORAL => CoralType::FIRE,
- Ids::HORN_CORAL => CoralType::HORN,
- Ids::TUBE_CORAL => CoralType::TUBE,
- ] as $id => $coralType){
- $this->mapSimple($id, fn() => Blocks::CORAL()->setCoralType($coralType)->setDead(false));
- }
- foreach([
- Ids::DEAD_BRAIN_CORAL => CoralType::BRAIN,
- Ids::DEAD_BUBBLE_CORAL => CoralType::BUBBLE,
- Ids::DEAD_FIRE_CORAL => CoralType::FIRE,
- Ids::DEAD_HORN_CORAL => CoralType::HORN,
- Ids::DEAD_TUBE_CORAL => CoralType::TUBE,
- ] as $id => $coralType){
- $this->mapSimple($id, fn() => Blocks::CORAL()->setCoralType($coralType)->setDead(true));
- }
-
- foreach([
- [CoralType::BRAIN, Ids::BRAIN_CORAL_FAN, Ids::DEAD_BRAIN_CORAL_FAN],
- [CoralType::BUBBLE, Ids::BUBBLE_CORAL_FAN, Ids::DEAD_BUBBLE_CORAL_FAN],
- [CoralType::FIRE, Ids::FIRE_CORAL_FAN, Ids::DEAD_FIRE_CORAL_FAN],
- [CoralType::HORN, Ids::HORN_CORAL_FAN, Ids::DEAD_HORN_CORAL_FAN],
- [CoralType::TUBE, Ids::TUBE_CORAL_FAN, Ids::DEAD_TUBE_CORAL_FAN],
- ] as [$coralType, $aliveId, $deadId]){
- $this->map($aliveId, fn(Reader $in) => Helper::decodeFloorCoralFan(Blocks::CORAL_FAN()->setCoralType($coralType)->setDead(false), $in));
- $this->map($deadId, fn(Reader $in) => Helper::decodeFloorCoralFan(Blocks::CORAL_FAN()->setCoralType($coralType)->setDead(true), $in));
- }
-
- foreach([
- [CoralType::BRAIN, Ids::BRAIN_CORAL_BLOCK, Ids::DEAD_BRAIN_CORAL_BLOCK],
- [CoralType::BUBBLE, Ids::BUBBLE_CORAL_BLOCK, Ids::DEAD_BUBBLE_CORAL_BLOCK],
- [CoralType::FIRE, Ids::FIRE_CORAL_BLOCK, Ids::DEAD_FIRE_CORAL_BLOCK],
- [CoralType::HORN, Ids::HORN_CORAL_BLOCK, Ids::DEAD_HORN_CORAL_BLOCK],
- [CoralType::TUBE, Ids::TUBE_CORAL_BLOCK, Ids::DEAD_TUBE_CORAL_BLOCK],
- ] as [$coralType, $aliveId, $deadId]){
- $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{
- $deserializer = function(Reader $in) : Block{
- $level = $in->readBoundedInt(StateNames::FILL_LEVEL, 0, 6);
- if($level === 0){
- $in->ignored(StateNames::CAULDRON_LIQUID);
- return Blocks::CAULDRON();
- }
-
- return (match($liquid = $in->readString(StateNames::CAULDRON_LIQUID)){
- StringValues::CAULDRON_LIQUID_WATER => Blocks::WATER_CAULDRON(),
- StringValues::CAULDRON_LIQUID_LAVA => Blocks::LAVA_CAULDRON(),
- StringValues::CAULDRON_LIQUID_POWDER_SNOW => throw new UnsupportedBlockStateException("Powder snow is not supported yet"),
- default => throw $in->badValueException(StateNames::CAULDRON_LIQUID, $liquid)
- })->setFillLevel($level);
- };
- $this->map(Ids::CAULDRON, $deserializer);
- }
-
- private function registerFlatWoodBlockDeserializers() : void{
- $this->map(Ids::ACACIA_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::ACACIA_BUTTON(), $in));
- $this->map(Ids::ACACIA_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::ACACIA_DOOR(), $in));
- $this->map(Ids::ACACIA_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::ACACIA_FENCE_GATE(), $in));
- $this->map(Ids::ACACIA_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::ACACIA_PRESSURE_PLATE(), $in));
- $this->map(Ids::ACACIA_STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::ACACIA_SIGN(), $in));
- $this->map(Ids::ACACIA_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::ACACIA_TRAPDOOR(), $in));
- $this->map(Ids::ACACIA_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::ACACIA_WALL_SIGN(), $in));
- $this->mapLog(Ids::ACACIA_LOG, Ids::STRIPPED_ACACIA_LOG, fn() => Blocks::ACACIA_LOG());
- $this->mapLog(Ids::ACACIA_WOOD, Ids::STRIPPED_ACACIA_WOOD, fn() => Blocks::ACACIA_WOOD());
- $this->mapSimple(Ids::ACACIA_FENCE, fn() => Blocks::ACACIA_FENCE());
- $this->mapSimple(Ids::ACACIA_PLANKS, fn() => Blocks::ACACIA_PLANKS());
- $this->mapSlab(Ids::ACACIA_SLAB, Ids::ACACIA_DOUBLE_SLAB, fn() => Blocks::ACACIA_SLAB());
- $this->mapStairs(Ids::ACACIA_STAIRS, fn() => Blocks::ACACIA_STAIRS());
-
- $this->map(Ids::BIRCH_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::BIRCH_BUTTON(), $in));
- $this->map(Ids::BIRCH_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::BIRCH_DOOR(), $in));
- $this->map(Ids::BIRCH_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::BIRCH_FENCE_GATE(), $in));
- $this->map(Ids::BIRCH_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::BIRCH_PRESSURE_PLATE(), $in));
- $this->map(Ids::BIRCH_STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::BIRCH_SIGN(), $in));
- $this->map(Ids::BIRCH_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::BIRCH_TRAPDOOR(), $in));
- $this->map(Ids::BIRCH_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::BIRCH_WALL_SIGN(), $in));
- $this->mapLog(Ids::BIRCH_LOG, Ids::STRIPPED_BIRCH_LOG, fn() => Blocks::BIRCH_LOG());
- $this->mapLog(Ids::BIRCH_WOOD, Ids::STRIPPED_BIRCH_WOOD, fn() => Blocks::BIRCH_WOOD());
- $this->mapSimple(Ids::BIRCH_FENCE, fn() => Blocks::BIRCH_FENCE());
- $this->mapSimple(Ids::BIRCH_PLANKS, fn() => Blocks::BIRCH_PLANKS());
- $this->mapSlab(Ids::BIRCH_SLAB, Ids::BIRCH_DOUBLE_SLAB, fn() => Blocks::BIRCH_SLAB());
- $this->mapStairs(Ids::BIRCH_STAIRS, fn() => Blocks::BIRCH_STAIRS());
-
- $this->map(Ids::CHERRY_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::CHERRY_BUTTON(), $in));
- $this->map(Ids::CHERRY_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::CHERRY_DOOR(), $in));
- $this->map(Ids::CHERRY_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::CHERRY_FENCE_GATE(), $in));
- $this->map(Ids::CHERRY_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::CHERRY_PRESSURE_PLATE(), $in));
- $this->map(Ids::CHERRY_STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::CHERRY_SIGN(), $in));
- $this->map(Ids::CHERRY_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::CHERRY_TRAPDOOR(), $in));
- $this->map(Ids::CHERRY_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::CHERRY_WALL_SIGN(), $in));
- $this->mapLog(Ids::CHERRY_LOG, Ids::STRIPPED_CHERRY_LOG, fn() => Blocks::CHERRY_LOG());
- $this->mapSimple(Ids::CHERRY_FENCE, fn() => Blocks::CHERRY_FENCE());
- $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, 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));
- $this->map(Ids::CRIMSON_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::CRIMSON_DOOR(), $in));
- $this->map(Ids::CRIMSON_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::CRIMSON_FENCE_GATE(), $in));
- $this->map(Ids::CRIMSON_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::CRIMSON_PRESSURE_PLATE(), $in));
- $this->map(Ids::CRIMSON_STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::CRIMSON_SIGN(), $in));
- $this->map(Ids::CRIMSON_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::CRIMSON_TRAPDOOR(), $in));
- $this->map(Ids::CRIMSON_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::CRIMSON_WALL_SIGN(), $in));
- $this->mapLog(Ids::CRIMSON_HYPHAE, Ids::STRIPPED_CRIMSON_HYPHAE, fn() => Blocks::CRIMSON_HYPHAE());
- $this->mapLog(Ids::CRIMSON_STEM, Ids::STRIPPED_CRIMSON_STEM, fn() => Blocks::CRIMSON_STEM());
- $this->mapSimple(Ids::CRIMSON_FENCE, fn() => Blocks::CRIMSON_FENCE());
- $this->mapSimple(Ids::CRIMSON_PLANKS, fn() => Blocks::CRIMSON_PLANKS());
- $this->mapSlab(Ids::CRIMSON_SLAB, Ids::CRIMSON_DOUBLE_SLAB, fn() => Blocks::CRIMSON_SLAB());
- $this->mapStairs(Ids::CRIMSON_STAIRS, fn() => Blocks::CRIMSON_STAIRS());
-
- $this->map(Ids::DARKOAK_STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::DARK_OAK_SIGN(), $in));
- $this->map(Ids::DARKOAK_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::DARK_OAK_WALL_SIGN(), $in));
- $this->map(Ids::DARK_OAK_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::DARK_OAK_BUTTON(), $in));
- $this->map(Ids::DARK_OAK_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::DARK_OAK_DOOR(), $in));
- $this->map(Ids::DARK_OAK_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::DARK_OAK_FENCE_GATE(), $in));
- $this->map(Ids::DARK_OAK_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::DARK_OAK_PRESSURE_PLATE(), $in));
- $this->map(Ids::DARK_OAK_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::DARK_OAK_TRAPDOOR(), $in));
- $this->mapLog(Ids::DARK_OAK_LOG, Ids::STRIPPED_DARK_OAK_LOG, fn() => Blocks::DARK_OAK_LOG());
- $this->mapLog(Ids::DARK_OAK_WOOD, Ids::STRIPPED_DARK_OAK_WOOD, fn() => Blocks::DARK_OAK_WOOD());
- $this->mapSimple(Ids::DARK_OAK_FENCE, fn() => Blocks::DARK_OAK_FENCE());
- $this->mapSimple(Ids::DARK_OAK_PLANKS, fn() => Blocks::DARK_OAK_PLANKS());
- $this->mapSlab(Ids::DARK_OAK_SLAB, Ids::DARK_OAK_DOUBLE_SLAB, fn() => Blocks::DARK_OAK_SLAB());
- $this->mapStairs(Ids::DARK_OAK_STAIRS, fn() => Blocks::DARK_OAK_STAIRS());
-
- $this->map(Ids::JUNGLE_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::JUNGLE_BUTTON(), $in));
- $this->map(Ids::JUNGLE_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::JUNGLE_DOOR(), $in));
- $this->map(Ids::JUNGLE_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::JUNGLE_FENCE_GATE(), $in));
- $this->map(Ids::JUNGLE_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::JUNGLE_PRESSURE_PLATE(), $in));
- $this->map(Ids::JUNGLE_STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::JUNGLE_SIGN(), $in));
- $this->map(Ids::JUNGLE_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::JUNGLE_TRAPDOOR(), $in));
- $this->map(Ids::JUNGLE_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::JUNGLE_WALL_SIGN(), $in));
- $this->mapLog(Ids::JUNGLE_LOG, Ids::STRIPPED_JUNGLE_LOG, fn() => Blocks::JUNGLE_LOG());
- $this->mapLog(Ids::JUNGLE_WOOD, Ids::STRIPPED_JUNGLE_WOOD, fn() => Blocks::JUNGLE_WOOD());
- $this->mapSimple(Ids::JUNGLE_FENCE, fn() => Blocks::JUNGLE_FENCE());
- $this->mapSimple(Ids::JUNGLE_PLANKS, fn() => Blocks::JUNGLE_PLANKS());
- $this->mapSlab(Ids::JUNGLE_SLAB, Ids::JUNGLE_DOUBLE_SLAB, fn() => Blocks::JUNGLE_SLAB());
- $this->mapStairs(Ids::JUNGLE_STAIRS, fn() => Blocks::JUNGLE_STAIRS());
-
- $this->map(Ids::MANGROVE_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::MANGROVE_BUTTON(), $in));
- $this->map(Ids::MANGROVE_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::MANGROVE_DOOR(), $in));
- $this->map(Ids::MANGROVE_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::MANGROVE_FENCE_GATE(), $in));
- $this->map(Ids::MANGROVE_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::MANGROVE_PRESSURE_PLATE(), $in));
- $this->map(Ids::MANGROVE_STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::MANGROVE_SIGN(), $in));
- $this->map(Ids::MANGROVE_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::MANGROVE_TRAPDOOR(), $in));
- $this->map(Ids::MANGROVE_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::MANGROVE_WALL_SIGN(), $in));
- $this->mapLog(Ids::MANGROVE_LOG, Ids::STRIPPED_MANGROVE_LOG, fn() => Blocks::MANGROVE_LOG());
- $this->mapSimple(Ids::MANGROVE_FENCE, fn() => Blocks::MANGROVE_FENCE());
- $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, 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
- $this->map(Ids::WOODEN_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::OAK_BUTTON(), $in));
- $this->map(Ids::WOODEN_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::OAK_DOOR(), $in));
- $this->map(Ids::FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::OAK_FENCE_GATE(), $in));
- $this->map(Ids::WOODEN_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::OAK_PRESSURE_PLATE(), $in));
- $this->map(Ids::STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::OAK_SIGN(), $in));
- $this->map(Ids::TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::OAK_TRAPDOOR(), $in));
- $this->map(Ids::WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::OAK_WALL_SIGN(), $in));
- $this->mapLog(Ids::OAK_LOG, Ids::STRIPPED_OAK_LOG, fn() => Blocks::OAK_LOG());
- $this->mapLog(Ids::OAK_WOOD, Ids::STRIPPED_OAK_WOOD, fn() => Blocks::OAK_WOOD());
- $this->mapSimple(Ids::OAK_FENCE, fn() => Blocks::OAK_FENCE());
- $this->mapSimple(Ids::OAK_PLANKS, fn() => Blocks::OAK_PLANKS());
- $this->mapSlab(Ids::OAK_SLAB, Ids::OAK_DOUBLE_SLAB, fn() => Blocks::OAK_SLAB());
- $this->mapStairs(Ids::OAK_STAIRS, fn() => Blocks::OAK_STAIRS());
-
- $this->map(Ids::PALE_OAK_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::PALE_OAK_BUTTON(), $in));
- $this->map(Ids::PALE_OAK_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::PALE_OAK_DOOR(), $in));
- $this->map(Ids::PALE_OAK_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::PALE_OAK_FENCE_GATE(), $in));
- $this->map(Ids::PALE_OAK_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::PALE_OAK_PRESSURE_PLATE(), $in));
- $this->map(Ids::PALE_OAK_STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::PALE_OAK_SIGN(), $in));
- $this->map(Ids::PALE_OAK_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::PALE_OAK_TRAPDOOR(), $in));
- $this->map(Ids::PALE_OAK_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::PALE_OAK_WALL_SIGN(), $in));
- $this->mapLog(Ids::PALE_OAK_LOG, Ids::STRIPPED_PALE_OAK_LOG, fn() => Blocks::PALE_OAK_LOG());
- $this->mapLog(Ids::PALE_OAK_WOOD, Ids::STRIPPED_PALE_OAK_WOOD, fn() => Blocks::PALE_OAK_WOOD());
- $this->mapSimple(Ids::PALE_OAK_FENCE, fn() => Blocks::PALE_OAK_FENCE());
- $this->mapSimple(Ids::PALE_OAK_PLANKS, fn() => Blocks::PALE_OAK_PLANKS());
- $this->mapSlab(Ids::PALE_OAK_SLAB, Ids::PALE_OAK_DOUBLE_SLAB, fn() => Blocks::PALE_OAK_SLAB());
- $this->mapStairs(Ids::PALE_OAK_STAIRS, fn() => Blocks::PALE_OAK_STAIRS());
-
- $this->map(Ids::SPRUCE_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::SPRUCE_BUTTON(), $in));
- $this->map(Ids::SPRUCE_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::SPRUCE_DOOR(), $in));
- $this->map(Ids::SPRUCE_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::SPRUCE_FENCE_GATE(), $in));
- $this->map(Ids::SPRUCE_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::SPRUCE_PRESSURE_PLATE(), $in));
- $this->map(Ids::SPRUCE_STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::SPRUCE_SIGN(), $in));
- $this->map(Ids::SPRUCE_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::SPRUCE_TRAPDOOR(), $in));
- $this->map(Ids::SPRUCE_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::SPRUCE_WALL_SIGN(), $in));
- $this->mapLog(Ids::SPRUCE_LOG, Ids::STRIPPED_SPRUCE_LOG, fn() => Blocks::SPRUCE_LOG());
- $this->mapLog(Ids::SPRUCE_WOOD, Ids::STRIPPED_SPRUCE_WOOD, fn() => Blocks::SPRUCE_WOOD());
- $this->mapSimple(Ids::SPRUCE_FENCE, fn() => Blocks::SPRUCE_FENCE());
- $this->mapSimple(Ids::SPRUCE_PLANKS, fn() => Blocks::SPRUCE_PLANKS());
- $this->mapSlab(Ids::SPRUCE_SLAB, Ids::SPRUCE_DOUBLE_SLAB, fn() => Blocks::SPRUCE_SLAB());
- $this->mapStairs(Ids::SPRUCE_STAIRS, fn() => Blocks::SPRUCE_STAIRS());
-
- $this->map(Ids::WARPED_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::WARPED_BUTTON(), $in));
- $this->map(Ids::WARPED_DOOR, fn(Reader $in) => Helper::decodeDoor(Blocks::WARPED_DOOR(), $in));
- $this->map(Ids::WARPED_FENCE_GATE, fn(Reader $in) => Helper::decodeFenceGate(Blocks::WARPED_FENCE_GATE(), $in));
- $this->map(Ids::WARPED_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::WARPED_PRESSURE_PLATE(), $in));
- $this->map(Ids::WARPED_STANDING_SIGN, fn(Reader $in) => Helper::decodeFloorSign(Blocks::WARPED_SIGN(), $in));
- $this->map(Ids::WARPED_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::WARPED_TRAPDOOR(), $in));
- $this->map(Ids::WARPED_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::WARPED_WALL_SIGN(), $in));
- $this->mapLog(Ids::WARPED_HYPHAE, Ids::STRIPPED_WARPED_HYPHAE, fn() => Blocks::WARPED_HYPHAE());
- $this->mapLog(Ids::WARPED_STEM, Ids::STRIPPED_WARPED_STEM, fn() => Blocks::WARPED_STEM());
- $this->mapSimple(Ids::WARPED_FENCE, fn() => Blocks::WARPED_FENCE());
- $this->mapSimple(Ids::WARPED_PLANKS, fn() => Blocks::WARPED_PLANKS());
- $this->mapSlab(Ids::WARPED_SLAB, Ids::WARPED_DOUBLE_SLAB, fn() => Blocks::WARPED_SLAB());
- $this->mapStairs(Ids::WARPED_STAIRS, fn() => Blocks::WARPED_STAIRS());
- }
-
- private function registerLeavesDeserializers() : void{
- $this->map(Ids::ACACIA_LEAVES, fn(Reader $in) => Helper::decodeLeaves(Blocks::ACACIA_LEAVES(), $in));
- $this->map(Ids::AZALEA_LEAVES, fn(Reader $in) => Helper::decodeLeaves(Blocks::AZALEA_LEAVES(), $in));
- $this->map(Ids::AZALEA_LEAVES_FLOWERED, fn(Reader $in) => Helper::decodeLeaves(Blocks::FLOWERING_AZALEA_LEAVES(), $in));
- $this->map(Ids::BIRCH_LEAVES, fn(Reader $in) => Helper::decodeLeaves(Blocks::BIRCH_LEAVES(), $in));
- $this->map(Ids::CHERRY_LEAVES, fn(Reader $in) => Helper::decodeLeaves(Blocks::CHERRY_LEAVES(), $in));
- $this->map(Ids::DARK_OAK_LEAVES, fn(Reader $in) => Helper::decodeLeaves(Blocks::DARK_OAK_LEAVES(), $in));
- $this->map(Ids::JUNGLE_LEAVES, fn(Reader $in) => Helper::decodeLeaves(Blocks::JUNGLE_LEAVES(), $in));
- $this->map(Ids::MANGROVE_LEAVES, fn(Reader $in) => Helper::decodeLeaves(Blocks::MANGROVE_LEAVES(), $in));
- $this->map(Ids::OAK_LEAVES, fn(Reader $in) => Helper::decodeLeaves(Blocks::OAK_LEAVES(), $in));
- $this->map(Ids::PALE_OAK_LEAVES, fn(Reader $in) => Helper::decodeLeaves(Blocks::PALE_OAK_LEAVES(), $in));
- $this->map(Ids::SPRUCE_LEAVES, fn(Reader $in) => Helper::decodeLeaves(Blocks::SPRUCE_LEAVES(), $in));
- }
-
- private function registerSaplingDeserializers() : void{
- foreach([
- Ids::ACACIA_SAPLING => fn() => Blocks::ACACIA_SAPLING(),
- Ids::BIRCH_SAPLING => fn() => Blocks::BIRCH_SAPLING(),
- Ids::DARK_OAK_SAPLING => fn() => Blocks::DARK_OAK_SAPLING(),
- Ids::JUNGLE_SAPLING => fn() => Blocks::JUNGLE_SAPLING(),
- Ids::OAK_SAPLING => fn() => Blocks::OAK_SAPLING(),
- Ids::SPRUCE_SAPLING => fn() => Blocks::SPRUCE_SAPLING(),
- ] as $id => $getBlock){
- $this->map($id, fn(Reader $in) => Helper::decodeSapling($getBlock(), $in));
- }
- }
-
- 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()));
- }
- }
-
- /**
- * @phpstan-param \Closure(Reader) : (CopperMaterial&Block) $deserializer
- */
- private function mapCopper(
- string $normalId,
- string $waxedNormalId,
- string $exposedId,
- string $waxedExposedId,
- string $weatheredId,
- string $waxedWeatheredId,
- string $oxidizedId,
- string $waxedOxidizedId,
- \Closure $deserializer
- ) : void{
- foreach(Utils::stringifyKeys([
- $normalId => [CopperOxidation::NONE, false],
- $waxedNormalId => [CopperOxidation::NONE, true],
- $exposedId => [CopperOxidation::EXPOSED, false],
- $waxedExposedId => [CopperOxidation::EXPOSED, true],
- $weatheredId => [CopperOxidation::WEATHERED, false],
- $waxedWeatheredId => [CopperOxidation::WEATHERED, true],
- $oxidizedId => [CopperOxidation::OXIDIZED, false],
- $waxedOxidizedId => [CopperOxidation::OXIDIZED, true],
- ]) as $id => [$oxidation, $waxed]){
- $this->map($id, fn(Reader $in) => $deserializer($in)->setOxidation($oxidation)->setWaxed($waxed));
- }
- }
-
- private function registerCopperDeserializers() : void{
- $this->mapCopper(
- Ids::CUT_COPPER_SLAB,
- Ids::WAXED_CUT_COPPER_SLAB,
- Ids::EXPOSED_CUT_COPPER_SLAB,
- Ids::WAXED_EXPOSED_CUT_COPPER_SLAB,
- Ids::WEATHERED_CUT_COPPER_SLAB,
- Ids::WAXED_WEATHERED_CUT_COPPER_SLAB,
- Ids::OXIDIZED_CUT_COPPER_SLAB,
- Ids::WAXED_OXIDIZED_CUT_COPPER_SLAB,
- fn(Reader $in) => Helper::decodeSingleSlab(Blocks::CUT_COPPER_SLAB(), $in)
- );
- $this->mapCopper(
- Ids::DOUBLE_CUT_COPPER_SLAB,
- Ids::WAXED_DOUBLE_CUT_COPPER_SLAB,
- Ids::EXPOSED_DOUBLE_CUT_COPPER_SLAB,
- Ids::WAXED_EXPOSED_DOUBLE_CUT_COPPER_SLAB,
- Ids::WEATHERED_DOUBLE_CUT_COPPER_SLAB,
- Ids::WAXED_WEATHERED_DOUBLE_CUT_COPPER_SLAB,
- Ids::OXIDIZED_DOUBLE_CUT_COPPER_SLAB,
- Ids::WAXED_OXIDIZED_DOUBLE_CUT_COPPER_SLAB,
- fn(Reader $in) => Helper::decodeDoubleSlab(Blocks::CUT_COPPER_SLAB(), $in)
- );
-
- $this->mapCopper(
- Ids::COPPER_BULB,
- Ids::WAXED_COPPER_BULB,
- Ids::EXPOSED_COPPER_BULB,
- Ids::WAXED_EXPOSED_COPPER_BULB,
- Ids::WEATHERED_COPPER_BULB,
- Ids::WAXED_WEATHERED_COPPER_BULB,
- Ids::OXIDIZED_COPPER_BULB,
- Ids::WAXED_OXIDIZED_COPPER_BULB,
- fn(Reader $in) => Blocks::COPPER_BULB()
- ->setLit($in->readBool(StateNames::LIT))
- ->setPowered($in->readBool(StateNames::POWERED_BIT))
- );
- $this->mapCopper(
- Ids::COPPER_DOOR,
- Ids::WAXED_COPPER_DOOR,
- Ids::EXPOSED_COPPER_DOOR,
- Ids::WAXED_EXPOSED_COPPER_DOOR,
- Ids::WEATHERED_COPPER_DOOR,
- Ids::WAXED_WEATHERED_COPPER_DOOR,
- Ids::OXIDIZED_COPPER_DOOR,
- Ids::WAXED_OXIDIZED_COPPER_DOOR,
- fn(Reader $in) => Helper::decodeDoor(Blocks::COPPER_DOOR(), $in)
- );
- $this->mapCopper(
- Ids::COPPER_TRAPDOOR,
- Ids::WAXED_COPPER_TRAPDOOR,
- Ids::EXPOSED_COPPER_TRAPDOOR,
- Ids::WAXED_EXPOSED_COPPER_TRAPDOOR,
- Ids::WEATHERED_COPPER_TRAPDOOR,
- Ids::WAXED_WEATHERED_COPPER_TRAPDOOR,
- Ids::OXIDIZED_COPPER_TRAPDOOR,
- Ids::WAXED_OXIDIZED_COPPER_TRAPDOOR,
- fn(Reader $in) => Helper::decodeTrapdoor(Blocks::COPPER_TRAPDOOR(), $in)
- );
- $this->mapCopper(
- Ids::COPPER_BLOCK,
- Ids::WAXED_COPPER,
- Ids::EXPOSED_COPPER,
- Ids::WAXED_EXPOSED_COPPER,
- Ids::WEATHERED_COPPER,
- Ids::WAXED_WEATHERED_COPPER,
- Ids::OXIDIZED_COPPER,
- Ids::WAXED_OXIDIZED_COPPER,
- fn(Reader $in) => Blocks::COPPER()
- );
- $this->mapCopper(
- Ids::CHISELED_COPPER,
- Ids::WAXED_CHISELED_COPPER,
- Ids::EXPOSED_CHISELED_COPPER,
- Ids::WAXED_EXPOSED_CHISELED_COPPER,
- Ids::WEATHERED_CHISELED_COPPER,
- Ids::WAXED_WEATHERED_CHISELED_COPPER,
- Ids::OXIDIZED_CHISELED_COPPER,
- Ids::WAXED_OXIDIZED_CHISELED_COPPER,
- fn(Reader $in) => Blocks::CHISELED_COPPER()
- );
- $this->mapCopper(
- Ids::COPPER_GRATE,
- Ids::WAXED_COPPER_GRATE,
- Ids::EXPOSED_COPPER_GRATE,
- Ids::WAXED_EXPOSED_COPPER_GRATE,
- Ids::WEATHERED_COPPER_GRATE,
- Ids::WAXED_WEATHERED_COPPER_GRATE,
- Ids::OXIDIZED_COPPER_GRATE,
- Ids::WAXED_OXIDIZED_COPPER_GRATE,
- fn(Reader $in) => Blocks::COPPER_GRATE()
- );
- $this->mapCopper(
- Ids::CUT_COPPER,
- Ids::WAXED_CUT_COPPER,
- Ids::EXPOSED_CUT_COPPER,
- Ids::WAXED_EXPOSED_CUT_COPPER,
- Ids::WEATHERED_CUT_COPPER,
- Ids::WAXED_WEATHERED_CUT_COPPER,
- Ids::OXIDIZED_CUT_COPPER,
- Ids::WAXED_OXIDIZED_CUT_COPPER,
- fn(Reader $in) => Blocks::CUT_COPPER()
- );
- $this->mapCopper(
- Ids::CUT_COPPER_STAIRS,
- Ids::WAXED_CUT_COPPER_STAIRS,
- Ids::EXPOSED_CUT_COPPER_STAIRS,
- Ids::WAXED_EXPOSED_CUT_COPPER_STAIRS,
- Ids::WEATHERED_CUT_COPPER_STAIRS,
- Ids::WAXED_WEATHERED_CUT_COPPER_STAIRS,
- Ids::OXIDIZED_CUT_COPPER_STAIRS,
- Ids::WAXED_OXIDIZED_CUT_COPPER_STAIRS,
- fn(Reader $in) => Helper::decodeStairs(Blocks::CUT_COPPER_STAIRS(), $in)
- );
- }
-
- private function registerSimpleDeserializers() : void{
- $this->mapSimple(Ids::AIR, fn() => Blocks::AIR());
- $this->mapSimple(Ids::AMETHYST_BLOCK, fn() => Blocks::AMETHYST());
- $this->mapSimple(Ids::ANCIENT_DEBRIS, fn() => Blocks::ANCIENT_DEBRIS());
- $this->mapSimple(Ids::ANDESITE, fn() => Blocks::ANDESITE());
- $this->mapSimple(Ids::BARRIER, fn() => Blocks::BARRIER());
- $this->mapSimple(Ids::BEACON, fn() => Blocks::BEACON());
- $this->mapSimple(Ids::BLACKSTONE, fn() => Blocks::BLACKSTONE());
- $this->mapSimple(Ids::BLUE_ICE, fn() => Blocks::BLUE_ICE());
- $this->mapSimple(Ids::BOOKSHELF, fn() => Blocks::BOOKSHELF());
- $this->mapSimple(Ids::BRICK_BLOCK, fn() => Blocks::BRICKS());
- $this->mapSimple(Ids::BROWN_MUSHROOM, fn() => Blocks::BROWN_MUSHROOM());
- $this->mapSimple(Ids::BUDDING_AMETHYST, fn() => Blocks::BUDDING_AMETHYST());
- $this->mapSimple(Ids::CALCITE, fn() => Blocks::CALCITE());
- $this->mapSimple(Ids::CARTOGRAPHY_TABLE, fn() => Blocks::CARTOGRAPHY_TABLE());
- $this->mapSimple(Ids::CHEMICAL_HEAT, fn() => Blocks::CHEMICAL_HEAT());
- $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_RESIN_BRICKS, fn() => Blocks::CHISELED_RESIN_BRICKS());
- $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());
- $this->mapSimple(Ids::COAL_ORE, fn() => Blocks::COAL_ORE());
- $this->mapSimple(Ids::COBBLED_DEEPSLATE, fn() => Blocks::COBBLED_DEEPSLATE());
- $this->mapSimple(Ids::COBBLESTONE, fn() => Blocks::COBBLESTONE());
- $this->mapSimple(Ids::COPPER_ORE, fn() => Blocks::COPPER_ORE());
- $this->mapSimple(Ids::CRACKED_DEEPSLATE_BRICKS, fn() => Blocks::CRACKED_DEEPSLATE_BRICKS());
- $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());
- $this->mapSimple(Ids::DEEPSLATE_COPPER_ORE, fn() => Blocks::DEEPSLATE_COPPER_ORE());
- $this->mapSimple(Ids::DEEPSLATE_DIAMOND_ORE, fn() => Blocks::DEEPSLATE_DIAMOND_ORE());
- $this->mapSimple(Ids::DEEPSLATE_EMERALD_ORE, fn() => Blocks::DEEPSLATE_EMERALD_ORE());
- $this->mapSimple(Ids::DEEPSLATE_GOLD_ORE, fn() => Blocks::DEEPSLATE_GOLD_ORE());
- $this->mapSimple(Ids::DEEPSLATE_IRON_ORE, fn() => Blocks::DEEPSLATE_IRON_ORE());
- $this->mapSimple(Ids::DEEPSLATE_LAPIS_ORE, fn() => Blocks::DEEPSLATE_LAPIS_LAZULI_ORE());
- $this->mapSimple(Ids::DEEPSLATE_TILES, fn() => Blocks::DEEPSLATE_TILES());
- $this->mapSimple(Ids::DIAMOND_BLOCK, fn() => Blocks::DIAMOND());
- $this->mapSimple(Ids::DIAMOND_ORE, fn() => Blocks::DIAMOND_ORE());
- $this->mapSimple(Ids::DIORITE, fn() => Blocks::DIORITE());
- $this->mapSimple(Ids::DRAGON_EGG, fn() => Blocks::DRAGON_EGG());
- $this->mapSimple(Ids::DRIED_KELP_BLOCK, fn() => Blocks::DRIED_KELP());
- $this->mapSimple(Ids::ELEMENT_0, fn() => Blocks::ELEMENT_ZERO());
- $this->mapSimple(Ids::ELEMENT_1, fn() => Blocks::ELEMENT_HYDROGEN());
- $this->mapSimple(Ids::ELEMENT_10, fn() => Blocks::ELEMENT_NEON());
- $this->mapSimple(Ids::ELEMENT_100, fn() => Blocks::ELEMENT_FERMIUM());
- $this->mapSimple(Ids::ELEMENT_101, fn() => Blocks::ELEMENT_MENDELEVIUM());
- $this->mapSimple(Ids::ELEMENT_102, fn() => Blocks::ELEMENT_NOBELIUM());
- $this->mapSimple(Ids::ELEMENT_103, fn() => Blocks::ELEMENT_LAWRENCIUM());
- $this->mapSimple(Ids::ELEMENT_104, fn() => Blocks::ELEMENT_RUTHERFORDIUM());
- $this->mapSimple(Ids::ELEMENT_105, fn() => Blocks::ELEMENT_DUBNIUM());
- $this->mapSimple(Ids::ELEMENT_106, fn() => Blocks::ELEMENT_SEABORGIUM());
- $this->mapSimple(Ids::ELEMENT_107, fn() => Blocks::ELEMENT_BOHRIUM());
- $this->mapSimple(Ids::ELEMENT_108, fn() => Blocks::ELEMENT_HASSIUM());
- $this->mapSimple(Ids::ELEMENT_109, fn() => Blocks::ELEMENT_MEITNERIUM());
- $this->mapSimple(Ids::ELEMENT_11, fn() => Blocks::ELEMENT_SODIUM());
- $this->mapSimple(Ids::ELEMENT_110, fn() => Blocks::ELEMENT_DARMSTADTIUM());
- $this->mapSimple(Ids::ELEMENT_111, fn() => Blocks::ELEMENT_ROENTGENIUM());
- $this->mapSimple(Ids::ELEMENT_112, fn() => Blocks::ELEMENT_COPERNICIUM());
- $this->mapSimple(Ids::ELEMENT_113, fn() => Blocks::ELEMENT_NIHONIUM());
- $this->mapSimple(Ids::ELEMENT_114, fn() => Blocks::ELEMENT_FLEROVIUM());
- $this->mapSimple(Ids::ELEMENT_115, fn() => Blocks::ELEMENT_MOSCOVIUM());
- $this->mapSimple(Ids::ELEMENT_116, fn() => Blocks::ELEMENT_LIVERMORIUM());
- $this->mapSimple(Ids::ELEMENT_117, fn() => Blocks::ELEMENT_TENNESSINE());
- $this->mapSimple(Ids::ELEMENT_118, fn() => Blocks::ELEMENT_OGANESSON());
- $this->mapSimple(Ids::ELEMENT_12, fn() => Blocks::ELEMENT_MAGNESIUM());
- $this->mapSimple(Ids::ELEMENT_13, fn() => Blocks::ELEMENT_ALUMINUM());
- $this->mapSimple(Ids::ELEMENT_14, fn() => Blocks::ELEMENT_SILICON());
- $this->mapSimple(Ids::ELEMENT_15, fn() => Blocks::ELEMENT_PHOSPHORUS());
- $this->mapSimple(Ids::ELEMENT_16, fn() => Blocks::ELEMENT_SULFUR());
- $this->mapSimple(Ids::ELEMENT_17, fn() => Blocks::ELEMENT_CHLORINE());
- $this->mapSimple(Ids::ELEMENT_18, fn() => Blocks::ELEMENT_ARGON());
- $this->mapSimple(Ids::ELEMENT_19, fn() => Blocks::ELEMENT_POTASSIUM());
- $this->mapSimple(Ids::ELEMENT_2, fn() => Blocks::ELEMENT_HELIUM());
- $this->mapSimple(Ids::ELEMENT_20, fn() => Blocks::ELEMENT_CALCIUM());
- $this->mapSimple(Ids::ELEMENT_21, fn() => Blocks::ELEMENT_SCANDIUM());
- $this->mapSimple(Ids::ELEMENT_22, fn() => Blocks::ELEMENT_TITANIUM());
- $this->mapSimple(Ids::ELEMENT_23, fn() => Blocks::ELEMENT_VANADIUM());
- $this->mapSimple(Ids::ELEMENT_24, fn() => Blocks::ELEMENT_CHROMIUM());
- $this->mapSimple(Ids::ELEMENT_25, fn() => Blocks::ELEMENT_MANGANESE());
- $this->mapSimple(Ids::ELEMENT_26, fn() => Blocks::ELEMENT_IRON());
- $this->mapSimple(Ids::ELEMENT_27, fn() => Blocks::ELEMENT_COBALT());
- $this->mapSimple(Ids::ELEMENT_28, fn() => Blocks::ELEMENT_NICKEL());
- $this->mapSimple(Ids::ELEMENT_29, fn() => Blocks::ELEMENT_COPPER());
- $this->mapSimple(Ids::ELEMENT_3, fn() => Blocks::ELEMENT_LITHIUM());
- $this->mapSimple(Ids::ELEMENT_30, fn() => Blocks::ELEMENT_ZINC());
- $this->mapSimple(Ids::ELEMENT_31, fn() => Blocks::ELEMENT_GALLIUM());
- $this->mapSimple(Ids::ELEMENT_32, fn() => Blocks::ELEMENT_GERMANIUM());
- $this->mapSimple(Ids::ELEMENT_33, fn() => Blocks::ELEMENT_ARSENIC());
- $this->mapSimple(Ids::ELEMENT_34, fn() => Blocks::ELEMENT_SELENIUM());
- $this->mapSimple(Ids::ELEMENT_35, fn() => Blocks::ELEMENT_BROMINE());
- $this->mapSimple(Ids::ELEMENT_36, fn() => Blocks::ELEMENT_KRYPTON());
- $this->mapSimple(Ids::ELEMENT_37, fn() => Blocks::ELEMENT_RUBIDIUM());
- $this->mapSimple(Ids::ELEMENT_38, fn() => Blocks::ELEMENT_STRONTIUM());
- $this->mapSimple(Ids::ELEMENT_39, fn() => Blocks::ELEMENT_YTTRIUM());
- $this->mapSimple(Ids::ELEMENT_4, fn() => Blocks::ELEMENT_BERYLLIUM());
- $this->mapSimple(Ids::ELEMENT_40, fn() => Blocks::ELEMENT_ZIRCONIUM());
- $this->mapSimple(Ids::ELEMENT_41, fn() => Blocks::ELEMENT_NIOBIUM());
- $this->mapSimple(Ids::ELEMENT_42, fn() => Blocks::ELEMENT_MOLYBDENUM());
- $this->mapSimple(Ids::ELEMENT_43, fn() => Blocks::ELEMENT_TECHNETIUM());
- $this->mapSimple(Ids::ELEMENT_44, fn() => Blocks::ELEMENT_RUTHENIUM());
- $this->mapSimple(Ids::ELEMENT_45, fn() => Blocks::ELEMENT_RHODIUM());
- $this->mapSimple(Ids::ELEMENT_46, fn() => Blocks::ELEMENT_PALLADIUM());
- $this->mapSimple(Ids::ELEMENT_47, fn() => Blocks::ELEMENT_SILVER());
- $this->mapSimple(Ids::ELEMENT_48, fn() => Blocks::ELEMENT_CADMIUM());
- $this->mapSimple(Ids::ELEMENT_49, fn() => Blocks::ELEMENT_INDIUM());
- $this->mapSimple(Ids::ELEMENT_5, fn() => Blocks::ELEMENT_BORON());
- $this->mapSimple(Ids::ELEMENT_50, fn() => Blocks::ELEMENT_TIN());
- $this->mapSimple(Ids::ELEMENT_51, fn() => Blocks::ELEMENT_ANTIMONY());
- $this->mapSimple(Ids::ELEMENT_52, fn() => Blocks::ELEMENT_TELLURIUM());
- $this->mapSimple(Ids::ELEMENT_53, fn() => Blocks::ELEMENT_IODINE());
- $this->mapSimple(Ids::ELEMENT_54, fn() => Blocks::ELEMENT_XENON());
- $this->mapSimple(Ids::ELEMENT_55, fn() => Blocks::ELEMENT_CESIUM());
- $this->mapSimple(Ids::ELEMENT_56, fn() => Blocks::ELEMENT_BARIUM());
- $this->mapSimple(Ids::ELEMENT_57, fn() => Blocks::ELEMENT_LANTHANUM());
- $this->mapSimple(Ids::ELEMENT_58, fn() => Blocks::ELEMENT_CERIUM());
- $this->mapSimple(Ids::ELEMENT_59, fn() => Blocks::ELEMENT_PRASEODYMIUM());
- $this->mapSimple(Ids::ELEMENT_6, fn() => Blocks::ELEMENT_CARBON());
- $this->mapSimple(Ids::ELEMENT_60, fn() => Blocks::ELEMENT_NEODYMIUM());
- $this->mapSimple(Ids::ELEMENT_61, fn() => Blocks::ELEMENT_PROMETHIUM());
- $this->mapSimple(Ids::ELEMENT_62, fn() => Blocks::ELEMENT_SAMARIUM());
- $this->mapSimple(Ids::ELEMENT_63, fn() => Blocks::ELEMENT_EUROPIUM());
- $this->mapSimple(Ids::ELEMENT_64, fn() => Blocks::ELEMENT_GADOLINIUM());
- $this->mapSimple(Ids::ELEMENT_65, fn() => Blocks::ELEMENT_TERBIUM());
- $this->mapSimple(Ids::ELEMENT_66, fn() => Blocks::ELEMENT_DYSPROSIUM());
- $this->mapSimple(Ids::ELEMENT_67, fn() => Blocks::ELEMENT_HOLMIUM());
- $this->mapSimple(Ids::ELEMENT_68, fn() => Blocks::ELEMENT_ERBIUM());
- $this->mapSimple(Ids::ELEMENT_69, fn() => Blocks::ELEMENT_THULIUM());
- $this->mapSimple(Ids::ELEMENT_7, fn() => Blocks::ELEMENT_NITROGEN());
- $this->mapSimple(Ids::ELEMENT_70, fn() => Blocks::ELEMENT_YTTERBIUM());
- $this->mapSimple(Ids::ELEMENT_71, fn() => Blocks::ELEMENT_LUTETIUM());
- $this->mapSimple(Ids::ELEMENT_72, fn() => Blocks::ELEMENT_HAFNIUM());
- $this->mapSimple(Ids::ELEMENT_73, fn() => Blocks::ELEMENT_TANTALUM());
- $this->mapSimple(Ids::ELEMENT_74, fn() => Blocks::ELEMENT_TUNGSTEN());
- $this->mapSimple(Ids::ELEMENT_75, fn() => Blocks::ELEMENT_RHENIUM());
- $this->mapSimple(Ids::ELEMENT_76, fn() => Blocks::ELEMENT_OSMIUM());
- $this->mapSimple(Ids::ELEMENT_77, fn() => Blocks::ELEMENT_IRIDIUM());
- $this->mapSimple(Ids::ELEMENT_78, fn() => Blocks::ELEMENT_PLATINUM());
- $this->mapSimple(Ids::ELEMENT_79, fn() => Blocks::ELEMENT_GOLD());
- $this->mapSimple(Ids::ELEMENT_8, fn() => Blocks::ELEMENT_OXYGEN());
- $this->mapSimple(Ids::ELEMENT_80, fn() => Blocks::ELEMENT_MERCURY());
- $this->mapSimple(Ids::ELEMENT_81, fn() => Blocks::ELEMENT_THALLIUM());
- $this->mapSimple(Ids::ELEMENT_82, fn() => Blocks::ELEMENT_LEAD());
- $this->mapSimple(Ids::ELEMENT_83, fn() => Blocks::ELEMENT_BISMUTH());
- $this->mapSimple(Ids::ELEMENT_84, fn() => Blocks::ELEMENT_POLONIUM());
- $this->mapSimple(Ids::ELEMENT_85, fn() => Blocks::ELEMENT_ASTATINE());
- $this->mapSimple(Ids::ELEMENT_86, fn() => Blocks::ELEMENT_RADON());
- $this->mapSimple(Ids::ELEMENT_87, fn() => Blocks::ELEMENT_FRANCIUM());
- $this->mapSimple(Ids::ELEMENT_88, fn() => Blocks::ELEMENT_RADIUM());
- $this->mapSimple(Ids::ELEMENT_89, fn() => Blocks::ELEMENT_ACTINIUM());
- $this->mapSimple(Ids::ELEMENT_9, fn() => Blocks::ELEMENT_FLUORINE());
- $this->mapSimple(Ids::ELEMENT_90, fn() => Blocks::ELEMENT_THORIUM());
- $this->mapSimple(Ids::ELEMENT_91, fn() => Blocks::ELEMENT_PROTACTINIUM());
- $this->mapSimple(Ids::ELEMENT_92, fn() => Blocks::ELEMENT_URANIUM());
- $this->mapSimple(Ids::ELEMENT_93, fn() => Blocks::ELEMENT_NEPTUNIUM());
- $this->mapSimple(Ids::ELEMENT_94, fn() => Blocks::ELEMENT_PLUTONIUM());
- $this->mapSimple(Ids::ELEMENT_95, fn() => Blocks::ELEMENT_AMERICIUM());
- $this->mapSimple(Ids::ELEMENT_96, fn() => Blocks::ELEMENT_CURIUM());
- $this->mapSimple(Ids::ELEMENT_97, fn() => Blocks::ELEMENT_BERKELIUM());
- $this->mapSimple(Ids::ELEMENT_98, fn() => Blocks::ELEMENT_CALIFORNIUM());
- $this->mapSimple(Ids::ELEMENT_99, fn() => Blocks::ELEMENT_EINSTEINIUM());
- $this->mapSimple(Ids::EMERALD_BLOCK, fn() => Blocks::EMERALD());
- $this->mapSimple(Ids::EMERALD_ORE, fn() => Blocks::EMERALD_ORE());
- $this->mapSimple(Ids::ENCHANTING_TABLE, fn() => Blocks::ENCHANTING_TABLE());
- $this->mapSimple(Ids::END_BRICKS, fn() => Blocks::END_STONE_BRICKS());
- $this->mapSimple(Ids::END_STONE, fn() => Blocks::END_STONE());
- $this->mapSimple(Ids::FERN, fn() => Blocks::FERN());
- $this->mapSimple(Ids::FLETCHING_TABLE, fn() => Blocks::FLETCHING_TABLE());
- $this->mapSimple(Ids::GILDED_BLACKSTONE, fn() => Blocks::GILDED_BLACKSTONE());
- $this->mapSimple(Ids::GLASS, fn() => Blocks::GLASS());
- $this->mapSimple(Ids::GLASS_PANE, fn() => Blocks::GLASS_PANE());
- $this->mapSimple(Ids::GLOWINGOBSIDIAN, fn() => Blocks::GLOWING_OBSIDIAN());
- $this->mapSimple(Ids::GLOWSTONE, fn() => Blocks::GLOWSTONE());
- $this->mapSimple(Ids::GOLD_BLOCK, fn() => Blocks::GOLD());
- $this->mapSimple(Ids::GOLD_ORE, fn() => Blocks::GOLD_ORE());
- $this->mapSimple(Ids::GRANITE, fn() => Blocks::GRANITE());
- $this->mapSimple(Ids::GRASS_BLOCK, fn() => Blocks::GRASS());
- $this->mapSimple(Ids::GRASS_PATH, fn() => Blocks::GRASS_PATH());
- $this->mapSimple(Ids::GRAVEL, fn() => Blocks::GRAVEL());
- $this->mapSimple(Ids::HANGING_ROOTS, fn() => Blocks::HANGING_ROOTS());
- $this->mapSimple(Ids::HARD_GLASS, fn() => Blocks::HARDENED_GLASS());
- $this->mapSimple(Ids::HARD_GLASS_PANE, fn() => Blocks::HARDENED_GLASS_PANE());
- $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());
- $this->mapSimple(Ids::IRON_BARS, fn() => Blocks::IRON_BARS());
- $this->mapSimple(Ids::IRON_BLOCK, fn() => Blocks::IRON());
- $this->mapSimple(Ids::IRON_ORE, fn() => Blocks::IRON_ORE());
- $this->mapSimple(Ids::JUKEBOX, fn() => Blocks::JUKEBOX());
- $this->mapSimple(Ids::LAPIS_BLOCK, fn() => Blocks::LAPIS_LAZULI());
- $this->mapSimple(Ids::LAPIS_ORE, fn() => Blocks::LAPIS_LAZULI_ORE());
- $this->mapSimple(Ids::MAGMA, fn() => Blocks::MAGMA());
- $this->mapSimple(Ids::MANGROVE_ROOTS, fn() => Blocks::MANGROVE_ROOTS());
- $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());
- $this->mapSimple(Ids::NETHER_BRICK, fn() => Blocks::NETHER_BRICKS());
- $this->mapSimple(Ids::NETHER_BRICK_FENCE, fn() => Blocks::NETHER_BRICK_FENCE());
- $this->mapSimple(Ids::NETHER_GOLD_ORE, fn() => Blocks::NETHER_GOLD_ORE());
- $this->mapSimple(Ids::NETHER_WART_BLOCK, fn() => Blocks::NETHER_WART_BLOCK());
- $this->mapSimple(Ids::NETHERITE_BLOCK, fn() => Blocks::NETHERITE());
- $this->mapSimple(Ids::NETHERRACK, fn() => Blocks::NETHERRACK());
- $this->mapSimple(Ids::NETHERREACTOR, fn() => Blocks::NETHER_REACTOR_CORE());
- $this->mapSimple(Ids::NOTEBLOCK, fn() => Blocks::NOTE_BLOCK());
- $this->mapSimple(Ids::OBSIDIAN, fn() => Blocks::OBSIDIAN());
- $this->mapSimple(Ids::PACKED_ICE, fn() => Blocks::PACKED_ICE());
- $this->mapSimple(Ids::PACKED_MUD, fn() => Blocks::PACKED_MUD());
- $this->mapSimple(Ids::PODZOL, fn() => Blocks::PODZOL());
- $this->mapSimple(Ids::POLISHED_ANDESITE, fn() => Blocks::POLISHED_ANDESITE());
- $this->mapSimple(Ids::POLISHED_BLACKSTONE, fn() => Blocks::POLISHED_BLACKSTONE());
- $this->mapSimple(Ids::POLISHED_BLACKSTONE_BRICKS, fn() => Blocks::POLISHED_BLACKSTONE_BRICKS());
- $this->mapSimple(Ids::POLISHED_DEEPSLATE, fn() => Blocks::POLISHED_DEEPSLATE());
- $this->mapSimple(Ids::POLISHED_DIORITE, fn() => Blocks::POLISHED_DIORITE());
- $this->mapSimple(Ids::POLISHED_GRANITE, fn() => Blocks::POLISHED_GRANITE());
- $this->mapSimple(Ids::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());
- $this->mapSimple(Ids::RAW_GOLD_BLOCK, fn() => Blocks::RAW_GOLD());
- $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::RESIN_BLOCK, fn() => Blocks::RESIN());
- $this->mapSimple(Ids::RESIN_BRICKS, fn() => Blocks::RESIN_BRICKS());
- $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 :(
- $this->mapSimple(Ids::SHROOMLIGHT, fn() => Blocks::SHROOMLIGHT());
- $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::DANDELION, fn() => Blocks::DANDELION());
-
- $this->mapSimple(Ids::ALLIUM, fn() => Blocks::ALLIUM());
- $this->mapSimple(Ids::CORNFLOWER, fn() => Blocks::CORNFLOWER());
- $this->mapSimple(Ids::AZURE_BLUET, fn() => Blocks::AZURE_BLUET());
- $this->mapSimple(Ids::LILY_OF_THE_VALLEY, fn() => Blocks::LILY_OF_THE_VALLEY());
- $this->mapSimple(Ids::BLUE_ORCHID, fn() => Blocks::BLUE_ORCHID());
- $this->mapSimple(Ids::OXEYE_DAISY, fn() => Blocks::OXEYE_DAISY());
- $this->mapSimple(Ids::POPPY, fn() => Blocks::POPPY());
- $this->mapSimple(Ids::ORANGE_TULIP, fn() => Blocks::ORANGE_TULIP());
- $this->mapSimple(Ids::PINK_TULIP, fn() => Blocks::PINK_TULIP());
- $this->mapSimple(Ids::RED_TULIP, fn() => Blocks::RED_TULIP());
- $this->mapSimple(Ids::WHITE_TULIP, fn() => Blocks::WHITE_TULIP());
- }
-
- private function registerDeserializers() : void{
- $this->map(Ids::ACTIVATOR_RAIL, function(Reader $in) : Block{
- return Blocks::ACTIVATOR_RAIL()
- ->setPowered($in->readBool(StateNames::RAIL_DATA_BIT))
- ->setShape($in->readBoundedInt(StateNames::RAIL_DIRECTION, 0, 5));
- });
- $this->map(Ids::AMETHYST_CLUSTER, function(Reader $in) : Block{
- return Blocks::AMETHYST_CLUSTER()
- ->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(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{
- return Blocks::BAMBOO()
- ->setLeafSize(match($value = $in->readString(StateNames::BAMBOO_LEAF_SIZE)){
- StringValues::BAMBOO_LEAF_SIZE_NO_LEAVES => Bamboo::NO_LEAVES,
- StringValues::BAMBOO_LEAF_SIZE_SMALL_LEAVES => Bamboo::SMALL_LEAVES,
- StringValues::BAMBOO_LEAF_SIZE_LARGE_LEAVES => Bamboo::LARGE_LEAVES,
- default => throw $in->badValueException(StateNames::BAMBOO_LEAF_SIZE, $value),
- })
- ->setReady($in->readBool(StateNames::AGE_BIT))
- ->setThick(match($value = $in->readString(StateNames::BAMBOO_STALK_THICKNESS)){
- StringValues::BAMBOO_STALK_THICKNESS_THIN => false,
- StringValues::BAMBOO_STALK_THICKNESS_THICK => true,
- default => throw $in->badValueException(StateNames::BAMBOO_STALK_THICKNESS, $value),
- });
- });
- $this->map(Ids::BAMBOO_SAPLING, function(Reader $in) : Block{
- return Blocks::BAMBOO_SAPLING()->setReady($in->readBool(StateNames::AGE_BIT));
- });
- $this->map(Ids::BARREL, function(Reader $in) : Block{
- return Blocks::BARREL()
- ->setFacing($in->readFacingDirection())
- ->setOpen($in->readBool(StateNames::OPEN_BIT));
- });
- $this->map(Ids::BASALT, function(Reader $in){
- return Blocks::BASALT()
- ->setAxis($in->readPillarAxis());
- });
- $this->map(Ids::BED, function(Reader $in) : Block{
- return Blocks::BED()
- ->setFacing($in->readLegacyHorizontalFacing())
- ->setHead($in->readBool(StateNames::HEAD_PIECE_BIT))
- ->setOccupied($in->readBool(StateNames::OCCUPIED_BIT));
- });
- $this->map(Ids::BEDROCK, function(Reader $in) : Block{
- return Blocks::BEDROCK()
- ->setBurnsForever($in->readBool(StateNames::INFINIBURN_BIT));
- });
- $this->map(Ids::BEETROOT, fn(Reader $in) => Helper::decodeCrops(Blocks::BEETROOTS(), $in));
- $this->map(Ids::BELL, function(Reader $in) : Block{
- $in->ignored(StateNames::TOGGLE_BIT); //only useful at runtime
- return Blocks::BELL()
- ->setFacing($in->readLegacyHorizontalFacing())
- ->setAttachmentType($in->readBellAttachmentType());
- });
- $this->map(Ids::BIG_DRIPLEAF, function(Reader $in) : Block{
- if($in->readBool(StateNames::BIG_DRIPLEAF_HEAD)){
- return Blocks::BIG_DRIPLEAF_HEAD()
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setLeafState(match($type = $in->readString(StateNames::BIG_DRIPLEAF_TILT)){
- StringValues::BIG_DRIPLEAF_TILT_NONE => DripleafState::STABLE,
- StringValues::BIG_DRIPLEAF_TILT_UNSTABLE => DripleafState::UNSTABLE,
- StringValues::BIG_DRIPLEAF_TILT_PARTIAL_TILT => DripleafState::PARTIAL_TILT,
- StringValues::BIG_DRIPLEAF_TILT_FULL_TILT => DripleafState::FULL_TILT,
- default => throw $in->badValueException(StateNames::BIG_DRIPLEAF_TILT, $type),
- });
- }else{
- $in->ignored(StateNames::BIG_DRIPLEAF_TILT);
- return Blocks::BIG_DRIPLEAF_STEM()->setFacing($in->readCardinalHorizontalFacing());
- }
- });
- $this->mapSlab(Ids::BLACKSTONE_SLAB, Ids::BLACKSTONE_DOUBLE_SLAB, fn() => Blocks::BLACKSTONE_SLAB());
- $this->mapStairs(Ids::BLACKSTONE_STAIRS, fn() => Blocks::BLACKSTONE_STAIRS());
- $this->map(Ids::BLACKSTONE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::BLACKSTONE_WALL(), $in));
- $this->map(Ids::BLAST_FURNACE, function(Reader $in) : Block{
- return Blocks::BLAST_FURNACE()
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setLit(false);
- });
- $this->map(Ids::BONE_BLOCK, function(Reader $in) : Block{
- $in->ignored(StateNames::DEPRECATED);
- return Blocks::BONE_BLOCK()->setAxis($in->readPillarAxis());
- });
- $this->map(Ids::BREWING_STAND, function(Reader $in) : Block{
- return Blocks::BREWING_STAND()
- ->setSlot(BrewingStandSlot::EAST, $in->readBool(StateNames::BREWING_STAND_SLOT_A_BIT))
- ->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()
- ->setAge($in->readBoundedInt(StateNames::AGE, 0, 15));
- });
- $this->map(Ids::CAKE, function(Reader $in) : Block{
- 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()
- ->setFacing($in->readCardinalHorizontalFacing());
- });
- $this->map(Ids::CAVE_VINES, function(Reader $in) : CaveVines{
- return Blocks::CAVE_VINES()
- ->setBerries(false)
- ->setHead(false)
- ->setAge($in->readBoundedInt(StateNames::GROWING_PLANT_AGE, 0, 25));
- });
- $this->map(Ids::CAVE_VINES_BODY_WITH_BERRIES, function(Reader $in) : CaveVines{
- return Blocks::CAVE_VINES()
- ->setBerries(true)
- ->setHead(false)
- ->setAge($in->readBoundedInt(StateNames::GROWING_PLANT_AGE, 0, 25));
- });
- $this->map(Ids::CAVE_VINES_HEAD_WITH_BERRIES, function(Reader $in) : CaveVines{
- return Blocks::CAVE_VINES()
- ->setBerries(true)
- ->setHead(true)
- ->setAge($in->readBoundedInt(StateNames::GROWING_PLANT_AGE, 0, 25));
- });
- $this->map(Ids::CHAIN, function(Reader $in) : Block{
- return Blocks::CHAIN()
- ->setAxis($in->readPillarAxis());
- });
- $this->map(Ids::CHISELED_BOOKSHELF, function(Reader $in) : Block{
- $block = Blocks::CHISELED_BOOKSHELF()
- ->setFacing($in->readLegacyHorizontalFacing());
-
- //we don't use API constant for bounds here as the data bounds might be different to what we support internally
- $flags = $in->readBoundedInt(StateNames::BOOKS_STORED, 0, (1 << 6) - 1);
- foreach(ChiseledBookshelfSlot::cases() as $slot){
- $block->setSlot($slot, ($flags & (1 << $slot->value)) !== 0);
- }
-
- return $block;
- });
- $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()
- ->setFacing($in->readCardinalHorizontalFacing());
- });
- $this->map(Ids::CHORUS_FLOWER, function(Reader $in) : Block{
- 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->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_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->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));
- $this->map(Ids::DAYLIGHT_DETECTOR_INVERTED, fn(Reader $in) => Helper::decodeDaylightSensor(Blocks::DAYLIGHT_SENSOR(), $in)
- ->setInverted(true));
- $this->map(Ids::DEEPSLATE, function(Reader $in) : Block{
- return Blocks::DEEPSLATE()
- ->setAxis($in->readPillarAxis());
- });
- $this->mapSlab(Ids::DEEPSLATE_BRICK_SLAB, Ids::DEEPSLATE_BRICK_DOUBLE_SLAB, fn() => Blocks::DEEPSLATE_BRICK_SLAB());
- $this->mapStairs(Ids::DEEPSLATE_BRICK_STAIRS, fn() => Blocks::DEEPSLATE_BRICK_STAIRS());
- $this->map(Ids::DEEPSLATE_BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::DEEPSLATE_BRICK_WALL(), $in));
- $this->map(Ids::DEEPSLATE_REDSTONE_ORE, fn() => Blocks::DEEPSLATE_REDSTONE_ORE()->setLit(false));
- $this->mapSlab(Ids::DEEPSLATE_TILE_SLAB, Ids::DEEPSLATE_TILE_DOUBLE_SLAB, fn() => Blocks::DEEPSLATE_TILE_SLAB());
- $this->mapStairs(Ids::DEEPSLATE_TILE_STAIRS, fn() => Blocks::DEEPSLATE_TILE_STAIRS());
- $this->map(Ids::DEEPSLATE_TILE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::DEEPSLATE_TILE_WALL(), $in));
- $this->map(Ids::DETECTOR_RAIL, function(Reader $in) : Block{
- return Blocks::DETECTOR_RAIL()
- ->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::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));
- $this->map(Ids::PEONY, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::PEONY(), $in));
- $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))
- ->setFacing($in->readCardinalHorizontalFacing());
- });
- $this->map(Ids::END_ROD, function(Reader $in) : Block{
- 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::FARMLAND, function(Reader $in) : Block{
- return Blocks::FARMLAND()
- ->setWetness($in->readBoundedInt(StateNames::MOISTURIZED_AMOUNT, 0, 7));
- });
- $this->map(Ids::FIRE, function(Reader $in) : Block{
- return Blocks::FIRE()
- ->setAge($in->readBoundedInt(StateNames::AGE, 0, 15));
- });
- $this->map(Ids::FLOWER_POT, function(Reader $in) : Block{
- $in->ignored(StateNames::UPDATE_BIT);
- return Blocks::FLOWER_POT();
- });
- $this->map(Ids::FLOWING_LAVA, fn(Reader $in) => Helper::decodeFlowingLiquid(Blocks::LAVA(), $in));
- $this->map(Ids::FLOWING_WATER, fn(Reader $in) => Helper::decodeFlowingLiquid(Blocks::WATER(), $in));
- $this->map(Ids::FRAME, fn(Reader $in) => Helper::decodeItemFrame(Blocks::ITEM_FRAME(), $in));
- $this->map(Ids::FROSTED_ICE, function(Reader $in) : Block{
- return Blocks::FROSTED_ICE()
- ->setAge($in->readBoundedInt(StateNames::AGE, 0, 3));
- });
- $this->map(Ids::FURNACE, function(Reader $in) : Block{
- return Blocks::FURNACE()
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setLit(false);
- });
- $this->map(Ids::GLOW_LICHEN, fn(Reader $in) => Blocks::GLOW_LICHEN()->setFaces($in->readFacingFlags()));
- $this->map(Ids::GLOW_FRAME, fn(Reader $in) => Helper::decodeItemFrame(Blocks::GLOWING_ITEM_FRAME(), $in));
- $this->map(Ids::GOLDEN_RAIL, function(Reader $in) : Block{
- return Blocks::POWERED_RAIL()
- ->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());
- });
- $this->map(Ids::HEAVY_WEIGHTED_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeWeightedPressurePlate(Blocks::WEIGHTED_PRESSURE_PLATE_HEAVY(), $in));
- $this->map(Ids::HOPPER, function(Reader $in) : Block{
- return Blocks::HOPPER()
- ->setFacing($in->readFacingWithoutUp())
- ->setPowered($in->readBool(StateNames::TOGGLE_BIT));
- });
- $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());
- });
- $this->map(Ids::LANTERN, function(Reader $in) : Block{
- return Blocks::LANTERN()
- ->setHanging($in->readBool(StateNames::HANGING));
- });
- $this->map(Ids::LARGE_AMETHYST_BUD, function(Reader $in) : Block{
- return Blocks::AMETHYST_CLUSTER()
- ->setStage(AmethystCluster::STAGE_LARGE_BUD)
- ->setFacing($in->readBlockFace());
- });
- $this->map(Ids::LAVA, fn(Reader $in) => Helper::decodeStillLiquid(Blocks::LAVA(), $in));
- $this->map(Ids::LECTERN, function(Reader $in) : Block{
- return Blocks::LECTERN()
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setProducingSignal($in->readBool(StateNames::POWERED_BIT));
- });
- $this->map(Ids::LEVER, function(Reader $in) : Block{
- return Blocks::LEVER()
- ->setActivated($in->readBool(StateNames::OPEN_BIT))
- ->setFacing(match($value = $in->readString(StateNames::LEVER_DIRECTION)){
- StringValues::LEVER_DIRECTION_DOWN_NORTH_SOUTH => LeverFacing::DOWN_AXIS_Z,
- StringValues::LEVER_DIRECTION_DOWN_EAST_WEST => LeverFacing::DOWN_AXIS_X,
- StringValues::LEVER_DIRECTION_UP_NORTH_SOUTH => LeverFacing::UP_AXIS_Z,
- StringValues::LEVER_DIRECTION_UP_EAST_WEST => LeverFacing::UP_AXIS_X,
- StringValues::LEVER_DIRECTION_NORTH => LeverFacing::NORTH,
- StringValues::LEVER_DIRECTION_SOUTH => LeverFacing::SOUTH,
- StringValues::LEVER_DIRECTION_WEST => LeverFacing::WEST,
- StringValues::LEVER_DIRECTION_EAST => LeverFacing::EAST,
- default => throw $in->badValueException(StateNames::LEVER_DIRECTION, $value),
- });
- });
- $this->map(Ids::LIGHTNING_ROD, function(Reader $in) : Block{
- return Blocks::LIGHTNING_ROD()
- ->setFacing($in->readFacingDirection());
- });
- $this->map(Ids::LIGHT_WEIGHTED_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeWeightedPressurePlate(Blocks::WEIGHTED_PRESSURE_PLATE_LIGHT(), $in));
- $this->map(Ids::LIT_BLAST_FURNACE, function(Reader $in) : Block{
- return Blocks::BLAST_FURNACE()
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setLit(true);
- });
- $this->map(Ids::LIT_DEEPSLATE_REDSTONE_ORE, fn() => Blocks::DEEPSLATE_REDSTONE_ORE()->setLit(true));
- $this->map(Ids::LIT_FURNACE, function(Reader $in) : Block{
- return Blocks::FURNACE()
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setLit(true);
- });
- $this->map(Ids::LIT_PUMPKIN, function(Reader $in) : Block{
- return Blocks::LIT_PUMPKIN()
- ->setFacing($in->readCardinalHorizontalFacing());
- });
- $this->map(Ids::LIT_REDSTONE_LAMP, function() : Block{
- return Blocks::REDSTONE_LAMP()
- ->setPowered(true);
- });
- $this->map(Ids::LIT_REDSTONE_ORE, function() : Block{
- return Blocks::REDSTONE_ORE()
- ->setLit(true);
- });
- $this->map(Ids::LIT_SMOKER, function(Reader $in) : Block{
- return Blocks::SMOKER()
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setLit(true);
- });
- $this->map(Ids::LOOM, function(Reader $in) : Block{
- 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->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));
- $this->map(Ids::MUDDY_MANGROVE_ROOTS, function(Reader $in) : Block{
- 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::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);
- return Blocks::PINK_PETALS()
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setCount(min($growth + 1, PinkPetals::MAX_COUNT));
- });
- $this->map(Ids::PITCHER_CROP, function(Reader $in) : Block{
- $growth = $in->readBoundedInt(StateNames::GROWTH, 0, 7);
- $top = $in->readBool(StateNames::UPPER_BLOCK_BIT);
- if($growth <= PitcherCrop::MAX_AGE){
- //top pitcher crop with age 0-2 is an invalid state
- //only the bottom half should exist in this case
- return $top ? Blocks::AIR() : Blocks::PITCHER_CROP()->setAge($growth);
- }
- return Blocks::DOUBLE_PITCHER_CROP()
- ->setAge(min($growth - PitcherCrop::MAX_AGE - 1, DoublePitcherCrop::MAX_AGE))
- ->setTop($top);
- });
- $this->map(Ids::PITCHER_PLANT, function(Reader $in) : Block{
- 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()
- ->setAxis($in->readPillarAxis());
- });
- $this->map(Ids::POLISHED_BLACKSTONE_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::POLISHED_BLACKSTONE_BUTTON(), $in));
- $this->mapSlab(Ids::POLISHED_BLACKSTONE_SLAB, Ids::POLISHED_BLACKSTONE_DOUBLE_SLAB, fn() => Blocks::POLISHED_BLACKSTONE_SLAB());
- $this->map(Ids::POLISHED_BLACKSTONE_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::POLISHED_BLACKSTONE_PRESSURE_PLATE(), $in));
- $this->mapStairs(Ids::POLISHED_BLACKSTONE_STAIRS, fn() => Blocks::POLISHED_BLACKSTONE_STAIRS());
- $this->map(Ids::POLISHED_BLACKSTONE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::POLISHED_BLACKSTONE_WALL(), $in));
- $this->mapSlab(Ids::POLISHED_BLACKSTONE_BRICK_SLAB, Ids::POLISHED_BLACKSTONE_BRICK_DOUBLE_SLAB, fn() => Blocks::POLISHED_BLACKSTONE_BRICK_SLAB());
- $this->mapStairs(Ids::POLISHED_BLACKSTONE_BRICK_STAIRS, fn() => Blocks::POLISHED_BLACKSTONE_BRICK_STAIRS());
- $this->map(Ids::POLISHED_BLACKSTONE_BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::POLISHED_BLACKSTONE_BRICK_WALL(), $in));
- $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)){
- StringValues::PORTAL_AXIS_UNKNOWN => Axis::X,
- StringValues::PORTAL_AXIS_X => Axis::X,
- StringValues::PORTAL_AXIS_Z => Axis::Z,
- default => throw $in->badValueException(StateNames::PORTAL_AXIS, $value),
- });
- });
- $this->map(Ids::POTATOES, fn(Reader $in) => Helper::decodeCrops(Blocks::POTATOES(), $in));
- $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->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
- return Blocks::PUMPKIN();
- });
- $this->map(Ids::PUMPKIN_STEM, fn(Reader $in) => Helper::decodeStem(Blocks::PUMPKIN_STEM(), $in));
- $this->map(Ids::PURPUR_BLOCK, function(Reader $in) : Block{
- $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) : 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_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);
- });
- $this->map(Ids::REDSTONE_ORE, function() : Block{
- return Blocks::REDSTONE_ORE()
- ->setLit(false);
- });
- $this->map(Ids::REDSTONE_TORCH, function(Reader $in) : Block{
- return Blocks::REDSTONE_TORCH()
- ->setFacing($in->readTorchFacing())
- ->setLit(true);
- });
- $this->map(Ids::REDSTONE_WIRE, function(Reader $in) : Block{
- return Blocks::REDSTONE_WIRE()
- ->setOutputSignalStrength($in->readBoundedInt(StateNames::REDSTONE_SIGNAL, 0, 15));
- });
- $this->map(Ids::REEDS, function(Reader $in) : Block{
- return Blocks::SUGARCANE()
- ->setAge($in->readBoundedInt(StateNames::AGE, 0, 15));
- });
- $this->mapSlab(Ids::RESIN_BRICK_SLAB, Ids::RESIN_BRICK_DOUBLE_SLAB, fn() => Blocks::RESIN_BRICK_SLAB());
- $this->mapStairs(Ids::RESIN_BRICK_STAIRS, fn() => Blocks::RESIN_BRICK_STAIRS());
- $this->map(Ids::RESIN_BRICK_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::RESIN_BRICK_WALL(), $in));
- $this->map(Ids::RESIN_CLUMP, fn(Reader $in) => Blocks::RESIN_CLUMP()->setFaces($in->readFacingFlags()));
- $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::SMOKER, function(Reader $in) : Block{
- return Blocks::SMOKER()
- ->setFacing($in->readCardinalHorizontalFacing())
- ->setLit(false);
- });
- $this->map(Ids::SMALL_AMETHYST_BUD, function(Reader $in) : Block{
- return Blocks::AMETHYST_CLUSTER()
- ->setStage(AmethystCluster::STAGE_SMALL_BUD)
- ->setFacing($in->readBlockFace());
- });
- $this->map(Ids::SMALL_DRIPLEAF_BLOCK, function(Reader $in) : Block{
- return Blocks::SMALL_DRIPLEAF()
- ->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();
- });
- $this->map(Ids::SOUL_LANTERN, function(Reader $in) : Block{
- return Blocks::SOUL_LANTERN()
- ->setHanging($in->readBool(StateNames::HANGING));
- });
- $this->map(Ids::SOUL_TORCH, function(Reader $in) : Block{
- return Blocks::SOUL_TORCH()
- ->setFacing($in->readTorchFacing());
- });
- $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));
- $this->mapStairs(Ids::STONE_STAIRS, fn() => Blocks::COBBLESTONE_STAIRS());
- $this->map(Ids::STONECUTTER_BLOCK, function(Reader $in) : Block{
- return Blocks::STONECUTTER()
- ->setFacing($in->readCardinalHorizontalFacing());
- });
- $this->map(Ids::SWEET_BERRY_BUSH, function(Reader $in) : Block{
- //berry bush only wants 0-3, but it can be bigger in MCPE due to misuse of GROWTH state which goes up to 7
- $growth = $in->readBoundedInt(StateNames::GROWTH, 0, 7);
- return Blocks::SWEET_BERRY_BUSH()
- ->setAge(min($growth, SweetBerryBush::STAGE_MATURE));
- });
- $this->map(Ids::TNT, function(Reader $in) : Block{
- return Blocks::TNT()
- ->setUnstable($in->readBool(StateNames::EXPLODE_BIT))
- ->setWorksUnderwater(false);
- });
- $this->map(Ids::TORCH, function(Reader $in) : Block{
- return Blocks::TORCH()
- ->setFacing($in->readTorchFacing());
- });
- $this->map(Ids::TORCHFLOWER_CROP, function(Reader $in) : Block{
- return Blocks::TORCHFLOWER_CROP()
- //this property can have values 0-7, but only 0-1 are valid
- ->setReady($in->readBoundedInt(StateNames::GROWTH, 0, 7) !== 0);
- });
- $this->map(Ids::TRAPPED_CHEST, function(Reader $in) : Block{
- return Blocks::TRAPPED_CHEST()
- ->setFacing($in->readCardinalHorizontalFacing());
- });
- $this->map(Ids::TRIP_WIRE, function(Reader $in) : Block{
- return Blocks::TRIPWIRE()
- ->setConnected($in->readBool(StateNames::ATTACHED_BIT))
- ->setDisarmed($in->readBool(StateNames::DISARMED_BIT))
- ->setSuspended($in->readBool(StateNames::SUSPENDED_BIT))
- ->setTriggered($in->readBool(StateNames::POWERED_BIT));
- });
- $this->map(Ids::TRIPWIRE_HOOK, function(Reader $in) : Block{
- return Blocks::TRIPWIRE_HOOK()
- ->setConnected($in->readBool(StateNames::ATTACHED_BIT))
- ->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());
- });
- $this->map(Ids::UNLIT_REDSTONE_TORCH, function(Reader $in) : Block{
- return Blocks::REDSTONE_TORCH()
- ->setFacing($in->readTorchFacing())
- ->setLit(false);
- });
- $this->map(Ids::UNPOWERED_COMPARATOR, fn(Reader $in) => Helper::decodeComparator(Blocks::REDSTONE_COMPARATOR(), $in));
- $this->map(Ids::UNPOWERED_REPEATER, fn(Reader $in) => Helper::decodeRepeater(Blocks::REDSTONE_REPEATER(), $in)
- ->setPowered(false));
- $this->map(Ids::VERDANT_FROGLIGHT, fn(Reader $in) => Blocks::FROGLIGHT()->setFroglightType(FroglightType::VERDANT)->setAxis($in->readPillarAxis()));
- $this->map(Ids::VINE, function(Reader $in) : Block{
- $vineDirectionFlags = $in->readBoundedInt(StateNames::VINE_DIRECTION_BITS, 0, 15);
- return Blocks::VINES()
- ->setFace(Facing::NORTH, ($vineDirectionFlags & BlockLegacyMetadata::VINE_FLAG_NORTH) !== 0)
- ->setFace(Facing::SOUTH, ($vineDirectionFlags & BlockLegacyMetadata::VINE_FLAG_SOUTH) !== 0)
- ->setFace(Facing::WEST, ($vineDirectionFlags & BlockLegacyMetadata::VINE_FLAG_WEST) !== 0)
- ->setFace(Facing::EAST, ($vineDirectionFlags & BlockLegacyMetadata::VINE_FLAG_EAST) !== 0);
- });
- $this->map(Ids::WALL_BANNER, function(Reader $in) : Block{
- return Blocks::WALL_BANNER()
- ->setFacing($in->readHorizontalFacing());
- });
- $this->map(Ids::WATER, fn(Reader $in) => Helper::decodeStillLiquid(Blocks::WATER(), $in));
-
- $this->map(Ids::WEEPING_VINES, function(Reader $in) : Block{
- return Blocks::WEEPING_VINES()
- ->setAge($in->readBoundedInt(StateNames::WEEPING_VINES_AGE, 0, 25));
- });
- $this->map(Ids::WHEAT, fn(Reader $in) => Helper::decodeCrops(Blocks::WHEAT(), $in));
- }
-
/** @throws BlockStateDeserializeException */
public function deserializeBlock(BlockStateData $blockStateData) : Block{
$id = $blockStateData->getName();
diff --git a/src/data/bedrock/block/convert/BlockStateWriter.php b/src/data/bedrock/block/convert/BlockStateWriter.php
index 63af92d10..d58bbd7c3 100644
--- a/src/data/bedrock/block/convert/BlockStateWriter.php
+++ b/src/data/bedrock/block/convert/BlockStateWriter.php
@@ -23,21 +23,11 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock\block\convert;
-use pocketmine\block\utils\BellAttachmentType;
-use pocketmine\block\utils\SlabType;
-use pocketmine\block\utils\WallConnectionType;
-use pocketmine\data\bedrock\block\BlockLegacyMetadata;
use pocketmine\data\bedrock\block\BlockStateData;
-use pocketmine\data\bedrock\block\BlockStateNames;
-use pocketmine\data\bedrock\block\BlockStateSerializeException;
-use pocketmine\data\bedrock\block\BlockStateStringValues as StringValues;
-use pocketmine\math\Axis;
-use pocketmine\math\Facing;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\tag\Tag;
-use pocketmine\utils\AssumptionFailedError;
final class BlockStateWriter{
@@ -73,209 +63,6 @@ final class BlockStateWriter{
return $this;
}
- /** @return $this */
- public function writeFacingDirection(int $value) : self{
- $this->writeInt(BlockStateNames::FACING_DIRECTION, match($value){
- Facing::DOWN => 0,
- Facing::UP => 1,
- Facing::NORTH => 2,
- Facing::SOUTH => 3,
- Facing::WEST => 4,
- Facing::EAST => 5,
- default => throw new BlockStateSerializeException("Invalid Facing $value")
- });
- return $this;
- }
-
- /** @return $this */
- public function writeBlockFace(int $value) : self{
- $this->writeString(BlockStateNames::MC_BLOCK_FACE, match($value){
- Facing::DOWN => StringValues::MC_BLOCK_FACE_DOWN,
- Facing::UP => StringValues::MC_BLOCK_FACE_UP,
- Facing::NORTH => StringValues::MC_BLOCK_FACE_NORTH,
- Facing::SOUTH => StringValues::MC_BLOCK_FACE_SOUTH,
- Facing::WEST => StringValues::MC_BLOCK_FACE_WEST,
- Facing::EAST => StringValues::MC_BLOCK_FACE_EAST,
- default => throw new BlockStateSerializeException("Invalid Facing $value")
- });
- return $this;
- }
-
- /**
- * @param int[] $faces
- * @phpstan-param array $faces
- * @return $this
- */
- public function writeFacingFlags(array $faces) : self{
- $result = 0;
- foreach($faces as $face){
- $result |= match($face){
- Facing::DOWN => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_DOWN,
- Facing::UP => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_UP,
- Facing::NORTH => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_NORTH,
- Facing::SOUTH => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_SOUTH,
- Facing::WEST => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_WEST,
- Facing::EAST => BlockLegacyMetadata::MULTI_FACE_DIRECTION_FLAG_EAST,
- default => throw new AssumptionFailedError("Unhandled face $face")
- };
- }
-
- return $this->writeInt(BlockStateNames::MULTI_FACE_DIRECTION_BITS, $result);
- }
-
- /** @return $this */
- public function writeEndRodFacingDirection(int $value) : self{
- //end rods are stupid in bedrock and have everything except up/down the wrong way round
- return $this->writeFacingDirection(Facing::axis($value) !== Axis::Y ? Facing::opposite($value) : $value);
- }
-
- /** @return $this */
- public function writeHorizontalFacing(int $value) : self{
- if($value === Facing::UP || $value === Facing::DOWN){
- throw new BlockStateSerializeException("Y-axis facing is not allowed");
- }
-
- return $this->writeFacingDirection($value);
- }
-
- /** @return $this */
- public function writeWeirdoHorizontalFacing(int $value) : self{
- $this->writeInt(BlockStateNames::WEIRDO_DIRECTION, match($value){
- Facing::EAST => 0,
- Facing::WEST => 1,
- Facing::SOUTH => 2,
- Facing::NORTH => 3,
- default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
- });
- return $this;
- }
-
- /** @return $this */
- public function writeLegacyHorizontalFacing(int $value) : self{
- $this->writeInt(BlockStateNames::DIRECTION, match($value){
- Facing::SOUTH => 0,
- Facing::WEST => 1,
- Facing::NORTH => 2,
- Facing::EAST => 3,
- default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
- });
- return $this;
- }
-
- /**
- * This is for trapdoors, because Mojang botched the conversion in 1.13
- * @return $this
- */
- public function write5MinusHorizontalFacing(int $value) : self{
- return $this->writeInt(BlockStateNames::DIRECTION, match($value){
- Facing::EAST => 0,
- Facing::WEST => 1,
- Facing::SOUTH => 2,
- Facing::NORTH => 3,
- default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
- });
- }
-
- /**
- * Used by pumpkins as of 1.20.0.23 beta
- * @return $this
- */
- public function writeCardinalHorizontalFacing(int $value) : self{
- return $this->writeString(BlockStateNames::MC_CARDINAL_DIRECTION, match($value){
- Facing::SOUTH => StringValues::MC_CARDINAL_DIRECTION_SOUTH,
- Facing::WEST => StringValues::MC_CARDINAL_DIRECTION_WEST,
- Facing::NORTH => StringValues::MC_CARDINAL_DIRECTION_NORTH,
- Facing::EAST => StringValues::MC_CARDINAL_DIRECTION_EAST,
- default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
- });
- }
-
- /** @return $this */
- public function writeCoralFacing(int $value) : self{
- $this->writeInt(BlockStateNames::CORAL_DIRECTION, match($value){
- Facing::WEST => 0,
- Facing::EAST => 1,
- Facing::NORTH => 2,
- Facing::SOUTH => 3,
- default => throw new BlockStateSerializeException("Invalid horizontal facing $value")
- });
- return $this;
- }
-
- /** @return $this */
- public function writeFacingWithoutDown(int $value) : self{
- if($value === Facing::DOWN){
- throw new BlockStateSerializeException("Invalid facing DOWN");
- }
- $this->writeFacingDirection($value);
- return $this;
- }
-
- /** @return $this */
- public function writeFacingWithoutUp(int $value) : self{
- if($value === Facing::UP){
- throw new BlockStateSerializeException("Invalid facing UP");
- }
- $this->writeFacingDirection($value);
- return $this;
- }
-
- /** @return $this */
- public function writePillarAxis(int $axis) : self{
- $this->writeString(BlockStateNames::PILLAR_AXIS, match($axis){
- Axis::X => StringValues::PILLAR_AXIS_X,
- Axis::Y => StringValues::PILLAR_AXIS_Y,
- Axis::Z => StringValues::PILLAR_AXIS_Z,
- default => throw new BlockStateSerializeException("Invalid axis $axis")
- });
- return $this;
- }
-
- /** @return $this */
- public function writeSlabPosition(SlabType $slabType) : self{
- $this->writeString(BlockStateNames::MC_VERTICAL_HALF, match($slabType){
- SlabType::TOP => StringValues::MC_VERTICAL_HALF_TOP,
- SlabType::BOTTOM => StringValues::MC_VERTICAL_HALF_BOTTOM,
- default => throw new BlockStateSerializeException("Invalid slab type " . $slabType->name)
- });
- return $this;
- }
-
- /** @return $this */
- public function writeTorchFacing(int $facing) : self{
- //TODO: horizontal directions are flipped (MCPE bug: https://bugs.mojang.com/browse/MCPE-152036)
- $this->writeString(BlockStateNames::TORCH_FACING_DIRECTION, match($facing){
- Facing::UP => StringValues::TORCH_FACING_DIRECTION_TOP,
- Facing::SOUTH => StringValues::TORCH_FACING_DIRECTION_NORTH,
- Facing::NORTH => StringValues::TORCH_FACING_DIRECTION_SOUTH,
- Facing::EAST => StringValues::TORCH_FACING_DIRECTION_WEST,
- Facing::WEST => StringValues::TORCH_FACING_DIRECTION_EAST,
- default => throw new BlockStateSerializeException("Invalid Torch facing $facing")
- });
- return $this;
- }
-
- /** @return $this */
- public function writeBellAttachmentType(BellAttachmentType $attachmentType) : self{
- $this->writeString(BlockStateNames::ATTACHMENT, match($attachmentType){
- BellAttachmentType::FLOOR => StringValues::ATTACHMENT_STANDING,
- BellAttachmentType::CEILING => StringValues::ATTACHMENT_HANGING,
- BellAttachmentType::ONE_WALL => StringValues::ATTACHMENT_SIDE,
- BellAttachmentType::TWO_WALLS => StringValues::ATTACHMENT_MULTIPLE,
- });
- return $this;
- }
-
- /** @return $this */
- public function writeWallConnectionType(string $name, ?WallConnectionType $wallConnectionType) : self{
- $this->writeString($name, match($wallConnectionType){
- null => StringValues::WALL_CONNECTION_TYPE_EAST_NONE,
- WallConnectionType::SHORT => StringValues::WALL_CONNECTION_TYPE_EAST_SHORT,
- WallConnectionType::TALL => StringValues::WALL_CONNECTION_TYPE_EAST_TALL,
- });
- return $this;
- }
-
public function getBlockStateData() : BlockStateData{
return BlockStateData::current($this->id, $this->states);
}
diff --git a/src/data/bedrock/block/convert/FlattenedIdModel.php b/src/data/bedrock/block/convert/FlattenedIdModel.php
new file mode 100644
index 000000000..50bf5cdd9
--- /dev/null
+++ b/src/data/bedrock/block/convert/FlattenedIdModel.php
@@ -0,0 +1,107 @@
+>
+ */
+ private array $idComponents = [];
+
+ /**
+ * @var Property[]
+ * @phpstan-var list>
+ */
+ private array $properties = [];
+
+ /**
+ * @phpstan-param TBlock $block
+ */
+ private function __construct(
+ private Block $block
+ ){}
+
+ /**
+ * @phpstan-template TBlock_ of Block
+ * @phpstan-param TBlock_ $block
+ * @return self
+ */
+ public static function create(Block $block) : self{
+ /** @phpstan-var self $result */
+ $result = new self($block);
+ return $result;
+ }
+
+ /** @phpstan-return TBlock */
+ public function getBlock() : Block{ return $this->block; }
+
+ /**
+ * @return string[]|StringProperty[]
+ * @phpstan-return list>
+ */
+ public function getIdComponents() : array{ return $this->idComponents; }
+
+ /**
+ * @return Property[]
+ * @phpstan-return list>
+ */
+ public function getProperties() : array{ return $this->properties; }
+
+ /**
+ * @param string[]|StringProperty[] $components
+ * @phpstan-param non-empty-list> $components
+ * @return $this
+ * @phpstan-this-out self
+ */
+ public function idComponents(array $components) : self{
+ $this->idComponents = $components;
+ return $this;
+ }
+
+ /**
+ * @param Property[] $properties
+ * @phpstan-param non-empty-list> $properties
+ * @return $this
+ * @phpstan-this-out self
+ */
+ public function properties(array $properties) : self{
+ $this->properties = $properties;
+ return $this;
+ }
+}
diff --git a/src/data/bedrock/block/convert/Model.php b/src/data/bedrock/block/convert/Model.php
new file mode 100644
index 000000000..3474a8932
--- /dev/null
+++ b/src/data/bedrock/block/convert/Model.php
@@ -0,0 +1,82 @@
+>
+ */
+ private array $properties = [];
+
+ /**
+ * @phpstan-param TBlock $block
+ */
+ private function __construct(
+ private Block $block,
+ private string $id
+ ){}
+
+ /** @phpstan-return TBlock */
+ public function getBlock() : Block{ return $this->block; }
+
+ public function getId() : string{ return $this->id; }
+
+ /**
+ * @return Property[]
+ * @phpstan-return list>
+ */
+ public function getProperties() : array{ return $this->properties; }
+
+ /**
+ * @phpstan-template TBlock_ of Block
+ * @phpstan-param TBlock_ $block
+ * @phpstan-return self
+ */
+ public static function create(Block $block, string $id) : self{
+ return new self($block, $id);
+ }
+
+ /**
+ * @param Property[] $properties
+ * @phpstan-param list> $properties
+ * @phpstan-return $this
+ */
+ public function properties(array $properties) : self{
+ $this->properties = $properties;
+ return $this;
+ }
+}
diff --git a/src/data/bedrock/block/convert/VanillaBlockMappings.php b/src/data/bedrock/block/convert/VanillaBlockMappings.php
new file mode 100644
index 000000000..15fd07659
--- /dev/null
+++ b/src/data/bedrock/block/convert/VanillaBlockMappings.php
@@ -0,0 +1,1662 @@
+mapSimple(Blocks::AIR(), Ids::AIR);
+ $reg->mapSimple(Blocks::AMETHYST(), Ids::AMETHYST_BLOCK);
+ $reg->mapSimple(Blocks::ANCIENT_DEBRIS(), Ids::ANCIENT_DEBRIS);
+ $reg->mapSimple(Blocks::ANDESITE(), Ids::ANDESITE);
+ $reg->mapSimple(Blocks::BARRIER(), Ids::BARRIER);
+ $reg->mapSimple(Blocks::BEACON(), Ids::BEACON);
+ $reg->mapSimple(Blocks::BLACKSTONE(), Ids::BLACKSTONE);
+ $reg->mapSimple(Blocks::BLUE_ICE(), Ids::BLUE_ICE);
+ $reg->mapSimple(Blocks::BOOKSHELF(), Ids::BOOKSHELF);
+ $reg->mapSimple(Blocks::BRICKS(), Ids::BRICK_BLOCK);
+ $reg->mapSimple(Blocks::BROWN_MUSHROOM(), Ids::BROWN_MUSHROOM);
+ $reg->mapSimple(Blocks::BUDDING_AMETHYST(), Ids::BUDDING_AMETHYST);
+ $reg->mapSimple(Blocks::CALCITE(), Ids::CALCITE);
+ $reg->mapSimple(Blocks::CARTOGRAPHY_TABLE(), Ids::CARTOGRAPHY_TABLE);
+ $reg->mapSimple(Blocks::CHEMICAL_HEAT(), Ids::CHEMICAL_HEAT);
+ $reg->mapSimple(Blocks::CHISELED_DEEPSLATE(), Ids::CHISELED_DEEPSLATE);
+ $reg->mapSimple(Blocks::CHISELED_NETHER_BRICKS(), Ids::CHISELED_NETHER_BRICKS);
+ $reg->mapSimple(Blocks::CHISELED_POLISHED_BLACKSTONE(), Ids::CHISELED_POLISHED_BLACKSTONE);
+ $reg->mapSimple(Blocks::CHISELED_RED_SANDSTONE(), Ids::CHISELED_RED_SANDSTONE);
+ $reg->mapSimple(Blocks::CHISELED_RESIN_BRICKS(), Ids::CHISELED_RESIN_BRICKS);
+ $reg->mapSimple(Blocks::CHISELED_SANDSTONE(), Ids::CHISELED_SANDSTONE);
+ $reg->mapSimple(Blocks::CHISELED_STONE_BRICKS(), Ids::CHISELED_STONE_BRICKS);
+ $reg->mapSimple(Blocks::CHISELED_TUFF(), Ids::CHISELED_TUFF);
+ $reg->mapSimple(Blocks::CHISELED_TUFF_BRICKS(), Ids::CHISELED_TUFF_BRICKS);
+ $reg->mapSimple(Blocks::CHORUS_PLANT(), Ids::CHORUS_PLANT);
+ $reg->mapSimple(Blocks::CLAY(), Ids::CLAY);
+ $reg->mapSimple(Blocks::COAL(), Ids::COAL_BLOCK);
+ $reg->mapSimple(Blocks::COAL_ORE(), Ids::COAL_ORE);
+ $reg->mapSimple(Blocks::COBBLED_DEEPSLATE(), Ids::COBBLED_DEEPSLATE);
+ $reg->mapSimple(Blocks::COBBLESTONE(), Ids::COBBLESTONE);
+ $reg->mapSimple(Blocks::COBWEB(), Ids::WEB);
+ $reg->mapSimple(Blocks::COPPER_ORE(), Ids::COPPER_ORE);
+ $reg->mapSimple(Blocks::CRACKED_DEEPSLATE_BRICKS(), Ids::CRACKED_DEEPSLATE_BRICKS);
+ $reg->mapSimple(Blocks::CRACKED_DEEPSLATE_TILES(), Ids::CRACKED_DEEPSLATE_TILES);
+ $reg->mapSimple(Blocks::CRACKED_NETHER_BRICKS(), Ids::CRACKED_NETHER_BRICKS);
+ $reg->mapSimple(Blocks::CRACKED_POLISHED_BLACKSTONE_BRICKS(), Ids::CRACKED_POLISHED_BLACKSTONE_BRICKS);
+ $reg->mapSimple(Blocks::CRACKED_STONE_BRICKS(), Ids::CRACKED_STONE_BRICKS);
+ $reg->mapSimple(Blocks::CRAFTING_TABLE(), Ids::CRAFTING_TABLE);
+ $reg->mapSimple(Blocks::CRIMSON_ROOTS(), Ids::CRIMSON_ROOTS);
+ $reg->mapSimple(Blocks::CRYING_OBSIDIAN(), Ids::CRYING_OBSIDIAN);
+ $reg->mapSimple(Blocks::DANDELION(), Ids::DANDELION);
+ $reg->mapSimple(Blocks::CUT_RED_SANDSTONE(), Ids::CUT_RED_SANDSTONE);
+ $reg->mapSimple(Blocks::CUT_SANDSTONE(), Ids::CUT_SANDSTONE);
+ $reg->mapSimple(Blocks::DARK_PRISMARINE(), Ids::DARK_PRISMARINE);
+ $reg->mapSimple(Blocks::DEAD_BUSH(), Ids::DEADBUSH);
+ $reg->mapSimple(Blocks::DEEPSLATE_BRICKS(), Ids::DEEPSLATE_BRICKS);
+ $reg->mapSimple(Blocks::DEEPSLATE_COAL_ORE(), Ids::DEEPSLATE_COAL_ORE);
+ $reg->mapSimple(Blocks::DEEPSLATE_COPPER_ORE(), Ids::DEEPSLATE_COPPER_ORE);
+ $reg->mapSimple(Blocks::DEEPSLATE_DIAMOND_ORE(), Ids::DEEPSLATE_DIAMOND_ORE);
+ $reg->mapSimple(Blocks::DEEPSLATE_EMERALD_ORE(), Ids::DEEPSLATE_EMERALD_ORE);
+ $reg->mapSimple(Blocks::DEEPSLATE_GOLD_ORE(), Ids::DEEPSLATE_GOLD_ORE);
+ $reg->mapSimple(Blocks::DEEPSLATE_IRON_ORE(), Ids::DEEPSLATE_IRON_ORE);
+ $reg->mapSimple(Blocks::DEEPSLATE_LAPIS_LAZULI_ORE(), Ids::DEEPSLATE_LAPIS_ORE);
+ $reg->mapSimple(Blocks::DEEPSLATE_TILES(), Ids::DEEPSLATE_TILES);
+ $reg->mapSimple(Blocks::DIAMOND(), Ids::DIAMOND_BLOCK);
+ $reg->mapSimple(Blocks::DIAMOND_ORE(), Ids::DIAMOND_ORE);
+ $reg->mapSimple(Blocks::DIORITE(), Ids::DIORITE);
+ $reg->mapSimple(Blocks::DRAGON_EGG(), Ids::DRAGON_EGG);
+ $reg->mapSimple(Blocks::DRIED_KELP(), Ids::DRIED_KELP_BLOCK);
+ $reg->mapSimple(Blocks::ELEMENT_ACTINIUM(), Ids::ELEMENT_89);
+ $reg->mapSimple(Blocks::ELEMENT_ALUMINUM(), Ids::ELEMENT_13);
+ $reg->mapSimple(Blocks::ELEMENT_AMERICIUM(), Ids::ELEMENT_95);
+ $reg->mapSimple(Blocks::ELEMENT_ANTIMONY(), Ids::ELEMENT_51);
+ $reg->mapSimple(Blocks::ELEMENT_ARGON(), Ids::ELEMENT_18);
+ $reg->mapSimple(Blocks::ELEMENT_ARSENIC(), Ids::ELEMENT_33);
+ $reg->mapSimple(Blocks::ELEMENT_ASTATINE(), Ids::ELEMENT_85);
+ $reg->mapSimple(Blocks::ELEMENT_BARIUM(), Ids::ELEMENT_56);
+ $reg->mapSimple(Blocks::ELEMENT_BERKELIUM(), Ids::ELEMENT_97);
+ $reg->mapSimple(Blocks::ELEMENT_BERYLLIUM(), Ids::ELEMENT_4);
+ $reg->mapSimple(Blocks::ELEMENT_BISMUTH(), Ids::ELEMENT_83);
+ $reg->mapSimple(Blocks::ELEMENT_BOHRIUM(), Ids::ELEMENT_107);
+ $reg->mapSimple(Blocks::ELEMENT_BORON(), Ids::ELEMENT_5);
+ $reg->mapSimple(Blocks::ELEMENT_BROMINE(), Ids::ELEMENT_35);
+ $reg->mapSimple(Blocks::ELEMENT_CADMIUM(), Ids::ELEMENT_48);
+ $reg->mapSimple(Blocks::ELEMENT_CALCIUM(), Ids::ELEMENT_20);
+ $reg->mapSimple(Blocks::ELEMENT_CALIFORNIUM(), Ids::ELEMENT_98);
+ $reg->mapSimple(Blocks::ELEMENT_CARBON(), Ids::ELEMENT_6);
+ $reg->mapSimple(Blocks::ELEMENT_CERIUM(), Ids::ELEMENT_58);
+ $reg->mapSimple(Blocks::ELEMENT_CESIUM(), Ids::ELEMENT_55);
+ $reg->mapSimple(Blocks::ELEMENT_CHLORINE(), Ids::ELEMENT_17);
+ $reg->mapSimple(Blocks::ELEMENT_CHROMIUM(), Ids::ELEMENT_24);
+ $reg->mapSimple(Blocks::ELEMENT_COBALT(), Ids::ELEMENT_27);
+ $reg->mapSimple(Blocks::ELEMENT_COPERNICIUM(), Ids::ELEMENT_112);
+ $reg->mapSimple(Blocks::ELEMENT_COPPER(), Ids::ELEMENT_29);
+ $reg->mapSimple(Blocks::ELEMENT_CURIUM(), Ids::ELEMENT_96);
+ $reg->mapSimple(Blocks::ELEMENT_DARMSTADTIUM(), Ids::ELEMENT_110);
+ $reg->mapSimple(Blocks::ELEMENT_DUBNIUM(), Ids::ELEMENT_105);
+ $reg->mapSimple(Blocks::ELEMENT_DYSPROSIUM(), Ids::ELEMENT_66);
+ $reg->mapSimple(Blocks::ELEMENT_EINSTEINIUM(), Ids::ELEMENT_99);
+ $reg->mapSimple(Blocks::ELEMENT_ERBIUM(), Ids::ELEMENT_68);
+ $reg->mapSimple(Blocks::ELEMENT_EUROPIUM(), Ids::ELEMENT_63);
+ $reg->mapSimple(Blocks::ELEMENT_FERMIUM(), Ids::ELEMENT_100);
+ $reg->mapSimple(Blocks::ELEMENT_FLEROVIUM(), Ids::ELEMENT_114);
+ $reg->mapSimple(Blocks::ELEMENT_FLUORINE(), Ids::ELEMENT_9);
+ $reg->mapSimple(Blocks::ELEMENT_FRANCIUM(), Ids::ELEMENT_87);
+ $reg->mapSimple(Blocks::ELEMENT_GADOLINIUM(), Ids::ELEMENT_64);
+ $reg->mapSimple(Blocks::ELEMENT_GALLIUM(), Ids::ELEMENT_31);
+ $reg->mapSimple(Blocks::ELEMENT_GERMANIUM(), Ids::ELEMENT_32);
+ $reg->mapSimple(Blocks::ELEMENT_GOLD(), Ids::ELEMENT_79);
+ $reg->mapSimple(Blocks::ELEMENT_HAFNIUM(), Ids::ELEMENT_72);
+ $reg->mapSimple(Blocks::ELEMENT_HASSIUM(), Ids::ELEMENT_108);
+ $reg->mapSimple(Blocks::ELEMENT_HELIUM(), Ids::ELEMENT_2);
+ $reg->mapSimple(Blocks::ELEMENT_HOLMIUM(), Ids::ELEMENT_67);
+ $reg->mapSimple(Blocks::ELEMENT_HYDROGEN(), Ids::ELEMENT_1);
+ $reg->mapSimple(Blocks::ELEMENT_INDIUM(), Ids::ELEMENT_49);
+ $reg->mapSimple(Blocks::ELEMENT_IODINE(), Ids::ELEMENT_53);
+ $reg->mapSimple(Blocks::ELEMENT_IRIDIUM(), Ids::ELEMENT_77);
+ $reg->mapSimple(Blocks::ELEMENT_IRON(), Ids::ELEMENT_26);
+ $reg->mapSimple(Blocks::ELEMENT_KRYPTON(), Ids::ELEMENT_36);
+ $reg->mapSimple(Blocks::ELEMENT_LANTHANUM(), Ids::ELEMENT_57);
+ $reg->mapSimple(Blocks::ELEMENT_LAWRENCIUM(), Ids::ELEMENT_103);
+ $reg->mapSimple(Blocks::ELEMENT_LEAD(), Ids::ELEMENT_82);
+ $reg->mapSimple(Blocks::ELEMENT_LITHIUM(), Ids::ELEMENT_3);
+ $reg->mapSimple(Blocks::ELEMENT_LIVERMORIUM(), Ids::ELEMENT_116);
+ $reg->mapSimple(Blocks::ELEMENT_LUTETIUM(), Ids::ELEMENT_71);
+ $reg->mapSimple(Blocks::ELEMENT_MAGNESIUM(), Ids::ELEMENT_12);
+ $reg->mapSimple(Blocks::ELEMENT_MANGANESE(), Ids::ELEMENT_25);
+ $reg->mapSimple(Blocks::ELEMENT_MEITNERIUM(), Ids::ELEMENT_109);
+ $reg->mapSimple(Blocks::ELEMENT_MENDELEVIUM(), Ids::ELEMENT_101);
+ $reg->mapSimple(Blocks::ELEMENT_MERCURY(), Ids::ELEMENT_80);
+ $reg->mapSimple(Blocks::ELEMENT_MOLYBDENUM(), Ids::ELEMENT_42);
+ $reg->mapSimple(Blocks::ELEMENT_MOSCOVIUM(), Ids::ELEMENT_115);
+ $reg->mapSimple(Blocks::ELEMENT_NEODYMIUM(), Ids::ELEMENT_60);
+ $reg->mapSimple(Blocks::ELEMENT_NEON(), Ids::ELEMENT_10);
+ $reg->mapSimple(Blocks::ELEMENT_NEPTUNIUM(), Ids::ELEMENT_93);
+ $reg->mapSimple(Blocks::ELEMENT_NICKEL(), Ids::ELEMENT_28);
+ $reg->mapSimple(Blocks::ELEMENT_NIHONIUM(), Ids::ELEMENT_113);
+ $reg->mapSimple(Blocks::ELEMENT_NIOBIUM(), Ids::ELEMENT_41);
+ $reg->mapSimple(Blocks::ELEMENT_NITROGEN(), Ids::ELEMENT_7);
+ $reg->mapSimple(Blocks::ELEMENT_NOBELIUM(), Ids::ELEMENT_102);
+ $reg->mapSimple(Blocks::ELEMENT_OGANESSON(), Ids::ELEMENT_118);
+ $reg->mapSimple(Blocks::ELEMENT_OSMIUM(), Ids::ELEMENT_76);
+ $reg->mapSimple(Blocks::ELEMENT_OXYGEN(), Ids::ELEMENT_8);
+ $reg->mapSimple(Blocks::ELEMENT_PALLADIUM(), Ids::ELEMENT_46);
+ $reg->mapSimple(Blocks::ELEMENT_PHOSPHORUS(), Ids::ELEMENT_15);
+ $reg->mapSimple(Blocks::ELEMENT_PLATINUM(), Ids::ELEMENT_78);
+ $reg->mapSimple(Blocks::ELEMENT_PLUTONIUM(), Ids::ELEMENT_94);
+ $reg->mapSimple(Blocks::ELEMENT_POLONIUM(), Ids::ELEMENT_84);
+ $reg->mapSimple(Blocks::ELEMENT_POTASSIUM(), Ids::ELEMENT_19);
+ $reg->mapSimple(Blocks::ELEMENT_PRASEODYMIUM(), Ids::ELEMENT_59);
+ $reg->mapSimple(Blocks::ELEMENT_PROMETHIUM(), Ids::ELEMENT_61);
+ $reg->mapSimple(Blocks::ELEMENT_PROTACTINIUM(), Ids::ELEMENT_91);
+ $reg->mapSimple(Blocks::ELEMENT_RADIUM(), Ids::ELEMENT_88);
+ $reg->mapSimple(Blocks::ELEMENT_RADON(), Ids::ELEMENT_86);
+ $reg->mapSimple(Blocks::ELEMENT_RHENIUM(), Ids::ELEMENT_75);
+ $reg->mapSimple(Blocks::ELEMENT_RHODIUM(), Ids::ELEMENT_45);
+ $reg->mapSimple(Blocks::ELEMENT_ROENTGENIUM(), Ids::ELEMENT_111);
+ $reg->mapSimple(Blocks::ELEMENT_RUBIDIUM(), Ids::ELEMENT_37);
+ $reg->mapSimple(Blocks::ELEMENT_RUTHENIUM(), Ids::ELEMENT_44);
+ $reg->mapSimple(Blocks::ELEMENT_RUTHERFORDIUM(), Ids::ELEMENT_104);
+ $reg->mapSimple(Blocks::ELEMENT_SAMARIUM(), Ids::ELEMENT_62);
+ $reg->mapSimple(Blocks::ELEMENT_SCANDIUM(), Ids::ELEMENT_21);
+ $reg->mapSimple(Blocks::ELEMENT_SEABORGIUM(), Ids::ELEMENT_106);
+ $reg->mapSimple(Blocks::ELEMENT_SELENIUM(), Ids::ELEMENT_34);
+ $reg->mapSimple(Blocks::ELEMENT_SILICON(), Ids::ELEMENT_14);
+ $reg->mapSimple(Blocks::ELEMENT_SILVER(), Ids::ELEMENT_47);
+ $reg->mapSimple(Blocks::ELEMENT_SODIUM(), Ids::ELEMENT_11);
+ $reg->mapSimple(Blocks::ELEMENT_STRONTIUM(), Ids::ELEMENT_38);
+ $reg->mapSimple(Blocks::ELEMENT_SULFUR(), Ids::ELEMENT_16);
+ $reg->mapSimple(Blocks::ELEMENT_TANTALUM(), Ids::ELEMENT_73);
+ $reg->mapSimple(Blocks::ELEMENT_TECHNETIUM(), Ids::ELEMENT_43);
+ $reg->mapSimple(Blocks::ELEMENT_TELLURIUM(), Ids::ELEMENT_52);
+ $reg->mapSimple(Blocks::ELEMENT_TENNESSINE(), Ids::ELEMENT_117);
+ $reg->mapSimple(Blocks::ELEMENT_TERBIUM(), Ids::ELEMENT_65);
+ $reg->mapSimple(Blocks::ELEMENT_THALLIUM(), Ids::ELEMENT_81);
+ $reg->mapSimple(Blocks::ELEMENT_THORIUM(), Ids::ELEMENT_90);
+ $reg->mapSimple(Blocks::ELEMENT_THULIUM(), Ids::ELEMENT_69);
+ $reg->mapSimple(Blocks::ELEMENT_TIN(), Ids::ELEMENT_50);
+ $reg->mapSimple(Blocks::ELEMENT_TITANIUM(), Ids::ELEMENT_22);
+ $reg->mapSimple(Blocks::ELEMENT_TUNGSTEN(), Ids::ELEMENT_74);
+ $reg->mapSimple(Blocks::ELEMENT_URANIUM(), Ids::ELEMENT_92);
+ $reg->mapSimple(Blocks::ELEMENT_VANADIUM(), Ids::ELEMENT_23);
+ $reg->mapSimple(Blocks::ELEMENT_XENON(), Ids::ELEMENT_54);
+ $reg->mapSimple(Blocks::ELEMENT_YTTERBIUM(), Ids::ELEMENT_70);
+ $reg->mapSimple(Blocks::ELEMENT_YTTRIUM(), Ids::ELEMENT_39);
+ $reg->mapSimple(Blocks::ELEMENT_ZERO(), Ids::ELEMENT_0);
+ $reg->mapSimple(Blocks::ELEMENT_ZINC(), Ids::ELEMENT_30);
+ $reg->mapSimple(Blocks::ELEMENT_ZIRCONIUM(), Ids::ELEMENT_40);
+ $reg->mapSimple(Blocks::EMERALD(), Ids::EMERALD_BLOCK);
+ $reg->mapSimple(Blocks::EMERALD_ORE(), Ids::EMERALD_ORE);
+ $reg->mapSimple(Blocks::ENCHANTING_TABLE(), Ids::ENCHANTING_TABLE);
+ $reg->mapSimple(Blocks::END_STONE(), Ids::END_STONE);
+ $reg->mapSimple(Blocks::END_STONE_BRICKS(), Ids::END_BRICKS);
+ $reg->mapSimple(Blocks::FERN(), Ids::FERN);
+ $reg->mapSimple(Blocks::FLETCHING_TABLE(), Ids::FLETCHING_TABLE);
+ $reg->mapSimple(Blocks::GILDED_BLACKSTONE(), Ids::GILDED_BLACKSTONE);
+ $reg->mapSimple(Blocks::GLASS(), Ids::GLASS);
+ $reg->mapSimple(Blocks::GLASS_PANE(), Ids::GLASS_PANE);
+ $reg->mapSimple(Blocks::GLOWING_OBSIDIAN(), Ids::GLOWINGOBSIDIAN);
+ $reg->mapSimple(Blocks::GLOWSTONE(), Ids::GLOWSTONE);
+ $reg->mapSimple(Blocks::GOLD(), Ids::GOLD_BLOCK);
+ $reg->mapSimple(Blocks::GOLD_ORE(), Ids::GOLD_ORE);
+ $reg->mapSimple(Blocks::GRANITE(), Ids::GRANITE);
+ $reg->mapSimple(Blocks::GRASS(), Ids::GRASS_BLOCK);
+ $reg->mapSimple(Blocks::GRASS_PATH(), Ids::GRASS_PATH);
+ $reg->mapSimple(Blocks::GRAVEL(), Ids::GRAVEL);
+ $reg->mapSimple(Blocks::HANGING_ROOTS(), Ids::HANGING_ROOTS);
+ $reg->mapSimple(Blocks::HARDENED_CLAY(), Ids::HARDENED_CLAY);
+ $reg->mapSimple(Blocks::HARDENED_GLASS(), Ids::HARD_GLASS);
+ $reg->mapSimple(Blocks::HARDENED_GLASS_PANE(), Ids::HARD_GLASS_PANE);
+ $reg->mapSimple(Blocks::HONEYCOMB(), Ids::HONEYCOMB_BLOCK);
+ $reg->mapSimple(Blocks::ICE(), Ids::ICE);
+ $reg->mapSimple(Blocks::INFESTED_CHISELED_STONE_BRICK(), Ids::INFESTED_CHISELED_STONE_BRICKS);
+ $reg->mapSimple(Blocks::INFESTED_COBBLESTONE(), Ids::INFESTED_COBBLESTONE);
+ $reg->mapSimple(Blocks::INFESTED_CRACKED_STONE_BRICK(), Ids::INFESTED_CRACKED_STONE_BRICKS);
+ $reg->mapSimple(Blocks::INFESTED_MOSSY_STONE_BRICK(), Ids::INFESTED_MOSSY_STONE_BRICKS);
+ $reg->mapSimple(Blocks::INFESTED_STONE(), Ids::INFESTED_STONE);
+ $reg->mapSimple(Blocks::INFESTED_STONE_BRICK(), Ids::INFESTED_STONE_BRICKS);
+ $reg->mapSimple(Blocks::INFO_UPDATE(), Ids::INFO_UPDATE);
+ $reg->mapSimple(Blocks::INFO_UPDATE2(), Ids::INFO_UPDATE2);
+ $reg->mapSimple(Blocks::INVISIBLE_BEDROCK(), Ids::INVISIBLE_BEDROCK);
+ $reg->mapSimple(Blocks::IRON(), Ids::IRON_BLOCK);
+ $reg->mapSimple(Blocks::IRON_BARS(), Ids::IRON_BARS);
+ $reg->mapSimple(Blocks::IRON_ORE(), Ids::IRON_ORE);
+ $reg->mapSimple(Blocks::JUKEBOX(), Ids::JUKEBOX);
+ $reg->mapSimple(Blocks::LAPIS_LAZULI(), Ids::LAPIS_BLOCK);
+ $reg->mapSimple(Blocks::LAPIS_LAZULI_ORE(), Ids::LAPIS_ORE);
+ $reg->mapSimple(Blocks::LEGACY_STONECUTTER(), Ids::STONECUTTER);
+ $reg->mapSimple(Blocks::LILY_PAD(), Ids::WATERLILY);
+ $reg->mapSimple(Blocks::MAGMA(), Ids::MAGMA);
+ $reg->mapSimple(Blocks::MANGROVE_ROOTS(), Ids::MANGROVE_ROOTS);
+ $reg->mapSimple(Blocks::MELON(), Ids::MELON_BLOCK);
+ $reg->mapSimple(Blocks::MONSTER_SPAWNER(), Ids::MOB_SPAWNER);
+ $reg->mapSimple(Blocks::MOSSY_COBBLESTONE(), Ids::MOSSY_COBBLESTONE);
+ $reg->mapSimple(Blocks::MOSSY_STONE_BRICKS(), Ids::MOSSY_STONE_BRICKS);
+ $reg->mapSimple(Blocks::MUD(), Ids::MUD);
+ $reg->mapSimple(Blocks::MUD_BRICKS(), Ids::MUD_BRICKS);
+ $reg->mapSimple(Blocks::MYCELIUM(), Ids::MYCELIUM);
+ $reg->mapSimple(Blocks::NETHERITE(), Ids::NETHERITE_BLOCK);
+ $reg->mapSimple(Blocks::NETHERRACK(), Ids::NETHERRACK);
+ $reg->mapSimple(Blocks::NETHER_BRICKS(), Ids::NETHER_BRICK);
+ $reg->mapSimple(Blocks::NETHER_BRICK_FENCE(), Ids::NETHER_BRICK_FENCE);
+ $reg->mapSimple(Blocks::NETHER_GOLD_ORE(), Ids::NETHER_GOLD_ORE);
+ $reg->mapSimple(Blocks::NETHER_QUARTZ_ORE(), Ids::QUARTZ_ORE);
+ $reg->mapSimple(Blocks::NETHER_REACTOR_CORE(), Ids::NETHERREACTOR);
+ $reg->mapSimple(Blocks::NETHER_WART_BLOCK(), Ids::NETHER_WART_BLOCK);
+ $reg->mapSimple(Blocks::NOTE_BLOCK(), Ids::NOTEBLOCK);
+ $reg->mapSimple(Blocks::OBSIDIAN(), Ids::OBSIDIAN);
+ $reg->mapSimple(Blocks::PACKED_ICE(), Ids::PACKED_ICE);
+ $reg->mapSimple(Blocks::PACKED_MUD(), Ids::PACKED_MUD);
+ $reg->mapSimple(Blocks::PODZOL(), Ids::PODZOL);
+ $reg->mapSimple(Blocks::POLISHED_ANDESITE(), Ids::POLISHED_ANDESITE);
+ $reg->mapSimple(Blocks::POLISHED_BLACKSTONE(), Ids::POLISHED_BLACKSTONE);
+ $reg->mapSimple(Blocks::POLISHED_BLACKSTONE_BRICKS(), Ids::POLISHED_BLACKSTONE_BRICKS);
+ $reg->mapSimple(Blocks::POLISHED_DEEPSLATE(), Ids::POLISHED_DEEPSLATE);
+ $reg->mapSimple(Blocks::POLISHED_DIORITE(), Ids::POLISHED_DIORITE);
+ $reg->mapSimple(Blocks::POLISHED_GRANITE(), Ids::POLISHED_GRANITE);
+ $reg->mapSimple(Blocks::POLISHED_TUFF(), Ids::POLISHED_TUFF);
+ $reg->mapSimple(Blocks::PRISMARINE(), Ids::PRISMARINE);
+ $reg->mapSimple(Blocks::PRISMARINE_BRICKS(), Ids::PRISMARINE_BRICKS);
+ $reg->mapSimple(Blocks::QUARTZ_BRICKS(), Ids::QUARTZ_BRICKS);
+ $reg->mapSimple(Blocks::RAW_COPPER(), Ids::RAW_COPPER_BLOCK);
+ $reg->mapSimple(Blocks::RAW_GOLD(), Ids::RAW_GOLD_BLOCK);
+ $reg->mapSimple(Blocks::RAW_IRON(), Ids::RAW_IRON_BLOCK);
+ $reg->mapSimple(Blocks::REDSTONE(), Ids::REDSTONE_BLOCK);
+ $reg->mapSimple(Blocks::RED_MUSHROOM(), Ids::RED_MUSHROOM);
+ $reg->mapSimple(Blocks::RED_NETHER_BRICKS(), Ids::RED_NETHER_BRICK);
+ $reg->mapSimple(Blocks::RED_SAND(), Ids::RED_SAND);
+ $reg->mapSimple(Blocks::RED_SANDSTONE(), Ids::RED_SANDSTONE);
+ $reg->mapSimple(Blocks::REINFORCED_DEEPSLATE(), Ids::REINFORCED_DEEPSLATE);
+ $reg->mapSimple(Blocks::RESERVED6(), Ids::RESERVED6);
+ $reg->mapSimple(Blocks::RESIN(), Ids::RESIN_BLOCK);
+ $reg->mapSimple(Blocks::RESIN_BRICKS(), Ids::RESIN_BRICKS);
+ $reg->mapSimple(Blocks::SAND(), Ids::SAND);
+ $reg->mapSimple(Blocks::SANDSTONE(), Ids::SANDSTONE);
+ $reg->mapSimple(Blocks::SCULK(), Ids::SCULK);
+ $reg->mapSimple(Blocks::SEA_LANTERN(), Ids::SEA_LANTERN);
+ $reg->mapSimple(Blocks::SHROOMLIGHT(), Ids::SHROOMLIGHT);
+ $reg->mapSimple(Blocks::SHULKER_BOX(), Ids::UNDYED_SHULKER_BOX);
+ $reg->mapSimple(Blocks::SLIME(), Ids::SLIME);
+ $reg->mapSimple(Blocks::SMITHING_TABLE(), Ids::SMITHING_TABLE);
+ $reg->mapSimple(Blocks::SMOOTH_BASALT(), Ids::SMOOTH_BASALT);
+ $reg->mapSimple(Blocks::SMOOTH_RED_SANDSTONE(), Ids::SMOOTH_RED_SANDSTONE);
+ $reg->mapSimple(Blocks::SMOOTH_SANDSTONE(), Ids::SMOOTH_SANDSTONE);
+ $reg->mapSimple(Blocks::SMOOTH_STONE(), Ids::SMOOTH_STONE);
+ $reg->mapSimple(Blocks::SNOW(), Ids::SNOW);
+ $reg->mapSimple(Blocks::SOUL_SAND(), Ids::SOUL_SAND);
+ $reg->mapSimple(Blocks::SOUL_SOIL(), Ids::SOUL_SOIL);
+ $reg->mapSimple(Blocks::SPORE_BLOSSOM(), Ids::SPORE_BLOSSOM);
+ $reg->mapSimple(Blocks::STONE(), Ids::STONE);
+ $reg->mapSimple(Blocks::STONE_BRICKS(), Ids::STONE_BRICKS);
+ $reg->mapSimple(Blocks::TALL_GRASS(), Ids::SHORT_GRASS); //no, this is not a typo - tall_grass is now the double block, just to be confusing :(
+ $reg->mapSimple(Blocks::TINTED_GLASS(), Ids::TINTED_GLASS);
+ $reg->mapSimple(Blocks::TORCHFLOWER(), Ids::TORCHFLOWER);
+ $reg->mapSimple(Blocks::TUFF(), Ids::TUFF);
+ $reg->mapSimple(Blocks::TUFF_BRICKS(), Ids::TUFF_BRICKS);
+ $reg->mapSimple(Blocks::WARPED_WART_BLOCK(), Ids::WARPED_WART_BLOCK);
+ $reg->mapSimple(Blocks::WARPED_ROOTS(), Ids::WARPED_ROOTS);
+ $reg->mapSimple(Blocks::WITHER_ROSE(), Ids::WITHER_ROSE);
+
+ $reg->mapSimple(Blocks::ALLIUM(), Ids::ALLIUM);
+ $reg->mapSimple(Blocks::CORNFLOWER(), Ids::CORNFLOWER);
+ $reg->mapSimple(Blocks::AZURE_BLUET(), Ids::AZURE_BLUET);
+ $reg->mapSimple(Blocks::LILY_OF_THE_VALLEY(), Ids::LILY_OF_THE_VALLEY);
+ $reg->mapSimple(Blocks::BLUE_ORCHID(), Ids::BLUE_ORCHID);
+ $reg->mapSimple(Blocks::OXEYE_DAISY(), Ids::OXEYE_DAISY);
+ $reg->mapSimple(Blocks::POPPY(), Ids::POPPY);
+ $reg->mapSimple(Blocks::ORANGE_TULIP(), Ids::ORANGE_TULIP);
+ $reg->mapSimple(Blocks::PINK_TULIP(), Ids::PINK_TULIP);
+ $reg->mapSimple(Blocks::RED_TULIP(), Ids::RED_TULIP);
+ $reg->mapSimple(Blocks::WHITE_TULIP(), Ids::WHITE_TULIP);
+ }
+
+ private static function registerColoredMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ $reg->mapColored(Blocks::STAINED_HARDENED_GLASS(), "minecraft:hard_", "_stained_glass");
+ $reg->mapColored(Blocks::STAINED_HARDENED_GLASS_PANE(), "minecraft:hard_", "_stained_glass_pane");
+
+ $reg->mapColored(Blocks::CARPET(), "minecraft:", "_carpet");
+ $reg->mapColored(Blocks::CONCRETE(), "minecraft:", "_concrete");
+ $reg->mapColored(Blocks::CONCRETE_POWDER(), "minecraft:", "_concrete_powder");
+ $reg->mapColored(Blocks::DYED_SHULKER_BOX(), "minecraft:", "_shulker_box");
+ $reg->mapColored(Blocks::STAINED_CLAY(), "minecraft:", "_terracotta");
+ $reg->mapColored(Blocks::STAINED_GLASS(), "minecraft:", "_stained_glass");
+ $reg->mapColored(Blocks::STAINED_GLASS_PANE(), "minecraft:", "_stained_glass_pane");
+ $reg->mapColored(Blocks::WOOL(), "minecraft:", "_wool");
+
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::GLAZED_TERRACOTTA())
+ ->idComponents([
+ "minecraft:",
+ new ValueFromStringProperty("color", ValueMappings::getInstance()->dyeColorWithSilver, fn(GlazedTerracotta $b) => $b->getColor(), fn(GlazedTerracotta $b, DyeColor $v) => $b->setColor($v)),
+ "_glazed_terracotta"
+ ])
+ ->properties([$commonProperties->horizontalFacingClassic])
+ );
+ }
+
+ private static function registerCandleMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ $candleProperties = [
+ $commonProperties->lit,
+ new IntProperty(StateNames::CANDLES, 0, 3, fn(Candle $b) => $b->getCount(), fn(Candle $b, int $v) => $b->setCount($v), offset: 1),
+ ];
+ $cakeWithCandleProperties = [$commonProperties->lit];
+ $reg->mapModel(Model::create(Blocks::CANDLE(), Ids::CANDLE)->properties($candleProperties));
+ $reg->mapModel(Model::create(Blocks::CAKE_WITH_CANDLE(), Ids::CANDLE_CAKE)->properties($cakeWithCandleProperties));
+
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::DYED_CANDLE())
+ ->idComponents([
+ "minecraft:",
+ $commonProperties->dyeColorIdInfix,
+ "_candle"
+ ])
+ ->properties($candleProperties)
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::CAKE_WITH_DYED_CANDLE())
+ ->idComponents([
+ "minecraft:",
+ $commonProperties->dyeColorIdInfix,
+ "_candle_cake"
+ ])
+ ->properties($cakeWithCandleProperties)
+ );
+ }
+
+ private static function registerLeavesMappings(BlockSerializerDeserializerRegistrar $reg) : void{
+ $properties = [
+ new BoolProperty(StateNames::PERSISTENT_BIT, fn(Leaves $b) => $b->isNoDecay(), fn(Leaves $b, bool $v) => $b->setNoDecay($v)),
+ new BoolProperty(StateNames::UPDATE_BIT, fn(Leaves $b) => $b->isCheckDecay(), fn(Leaves $b, bool $v) => $b->setCheckDecay($v)),
+ ];
+ foreach([
+ Ids::ACACIA_LEAVES => Blocks::ACACIA_LEAVES(),
+ Ids::AZALEA_LEAVES => Blocks::AZALEA_LEAVES(),
+ Ids::AZALEA_LEAVES_FLOWERED => Blocks::FLOWERING_AZALEA_LEAVES(),
+ Ids::BIRCH_LEAVES => Blocks::BIRCH_LEAVES(),
+ Ids::CHERRY_LEAVES => Blocks::CHERRY_LEAVES(),
+ Ids::DARK_OAK_LEAVES => Blocks::DARK_OAK_LEAVES(),
+ Ids::JUNGLE_LEAVES => Blocks::JUNGLE_LEAVES(),
+ Ids::MANGROVE_LEAVES => Blocks::MANGROVE_LEAVES(),
+ Ids::OAK_LEAVES => Blocks::OAK_LEAVES(),
+ Ids::PALE_OAK_LEAVES => Blocks::PALE_OAK_LEAVES(),
+ Ids::SPRUCE_LEAVES => Blocks::SPRUCE_LEAVES()
+ ] as $id => $block){
+ $reg->mapModel(Model::create($block, $id)->properties($properties));
+ }
+ }
+
+ private static function registerSaplingMappings(BlockSerializerDeserializerRegistrar $reg) : void{
+ $properties = [
+ new BoolProperty(StateNames::AGE_BIT, fn(Sapling $b) => $b->isReady(), fn(Sapling $b, bool $v) => $b->setReady($v)),
+ ];
+ foreach([
+ Ids::ACACIA_SAPLING => Blocks::ACACIA_SAPLING(),
+ Ids::BIRCH_SAPLING => Blocks::BIRCH_SAPLING(),
+ Ids::DARK_OAK_SAPLING => Blocks::DARK_OAK_SAPLING(),
+ Ids::JUNGLE_SAPLING => Blocks::JUNGLE_SAPLING(),
+ Ids::OAK_SAPLING => Blocks::OAK_SAPLING(),
+ Ids::SPRUCE_SAPLING => Blocks::SPRUCE_SAPLING(),
+ ] as $id => $block){
+ $reg->mapModel(Model::create($block, $id)->properties($properties));
+ }
+ }
+
+ private static function registerPlantMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ $reg->mapModel(Model::create(Blocks::BEETROOTS(), Ids::BEETROOT)->properties([$commonProperties->cropAgeMax7]));
+ $reg->mapModel(Model::create(Blocks::CARROTS(), Ids::CARROTS)->properties([$commonProperties->cropAgeMax7]));
+ $reg->mapModel(Model::create(Blocks::POTATOES(), Ids::POTATOES)->properties([$commonProperties->cropAgeMax7]));
+ $reg->mapModel(Model::create(Blocks::WHEAT(), Ids::WHEAT)->properties([$commonProperties->cropAgeMax7]));
+
+ $reg->mapModel(Model::create(Blocks::MELON_STEM(), Ids::MELON_STEM)->properties($commonProperties->stemProperties));
+ $reg->mapModel(Model::create(Blocks::PUMPKIN_STEM(), Ids::PUMPKIN_STEM)->properties($commonProperties->stemProperties));
+
+ foreach([
+ [Blocks::DOUBLE_TALLGRASS(), Ids::TALL_GRASS],
+ [Blocks::LARGE_FERN(), Ids::LARGE_FERN],
+ [Blocks::LILAC(), Ids::LILAC],
+ [Blocks::PEONY(), Ids::PEONY],
+ [Blocks::ROSE_BUSH(), Ids::ROSE_BUSH],
+ [Blocks::SUNFLOWER(), Ids::SUNFLOWER],
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties([$commonProperties->doublePlantHalf]));
+ }
+
+ foreach([
+ [Blocks::BROWN_MUSHROOM_BLOCK(), Ids::BROWN_MUSHROOM_BLOCK],
+ [Blocks::RED_MUSHROOM_BLOCK(), Ids::RED_MUSHROOM_BLOCK]
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties([
+ new ValueFromIntProperty(StateNames::HUGE_MUSHROOM_BITS, ValueMappings::getInstance()->mushroomBlockType, fn(RedMushroomBlock $b) => $b->getMushroomBlockType(), fn(RedMushroomBlock $b, MushroomBlockType $v) => $b->setMushroomBlockType($v)),
+ ]));
+ }
+
+ $reg->mapModel(Model::create(Blocks::GLOW_LICHEN(), Ids::GLOW_LICHEN)->properties([$commonProperties->multiFacingFlags]));
+ $reg->mapModel(Model::create(Blocks::RESIN_CLUMP(), Ids::RESIN_CLUMP)->properties([$commonProperties->multiFacingFlags]));
+
+ $reg->mapModel(Model::create(Blocks::VINES(), Ids::VINE)->properties([
+ new ValueSetFromIntProperty(
+ StateNames::VINE_DIRECTION_BITS,
+ EnumFromRawStateMap::int(HorizontalFacingOption::class, fn(HorizontalFacingOption $case) => match($case) {
+ HorizontalFacingOption::NORTH => BlockLegacyMetadata::VINE_FLAG_NORTH,
+ HorizontalFacingOption::SOUTH => BlockLegacyMetadata::VINE_FLAG_SOUTH,
+ HorizontalFacingOption::WEST => BlockLegacyMetadata::VINE_FLAG_WEST,
+ HorizontalFacingOption::EAST => BlockLegacyMetadata::VINE_FLAG_EAST,
+ }),
+ //TODO: hack for lack of HorizontalFacing enum :(
+ fn(Vine $b) => $b->getFaces(),
+ fn(Vine $b, array $v) => $b->setFaces($v)
+ )
+ ]));
+
+ $reg->mapModel(Model::create(Blocks::SWEET_BERRY_BUSH(), Ids::SWEET_BERRY_BUSH)->properties([
+ //TODO: berry bush only wants 0-3, but it can be bigger in MCPE due to misuse of GROWTH state which goes up to 7
+ new IntProperty(StateNames::GROWTH, 0, 7, fn(SweetBerryBush $b) => $b->getAge(), fn(SweetBerryBush $b, int $v) => $b->setAge(min($v, SweetBerryBush::STAGE_MATURE)))
+ ]));
+ $reg->mapModel(Model::create(Blocks::TORCHFLOWER_CROP(), Ids::TORCHFLOWER_CROP)->properties([
+ //TODO: this property can have values 0-7, but only 0-1 are valid
+ new IntProperty(StateNames::GROWTH, 0, 7, fn(TorchflowerCrop $b) => $b->isReady() ? 1 : 0, fn(TorchflowerCrop $b, int $v) => $b->setReady($v !== 0))
+ ]));
+ }
+
+ private static function registerCoralMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::CORAL())->idComponents([...$commonProperties->coralIdPrefixes, "_coral"]));
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::CORAL_BLOCK())->idComponents([...$commonProperties->coralIdPrefixes, "_coral_block"]));
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::CORAL_FAN())
+ ->idComponents([...$commonProperties->coralIdPrefixes, "_coral_fan"])
+ ->properties([
+ //TODO: hack for lack of horizontal axis enum :(
+ new ValueFromIntProperty(StateNames::CORAL_FAN_DIRECTION, ValueMappings::getInstance()->coralAxis, fn(FloorCoralFan $b) => $b->getAxis()->value, fn(FloorCoralFan $b, int $v) => $b->setAxis(Axis::from($v)))
+ ])
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::WALL_CORAL_FAN())
+ ->idComponents([...$commonProperties->coralIdPrefixes, "_coral_wall_fan"])
+ ->properties([
+ new ValueFromIntProperty(StateNames::CORAL_DIRECTION, ValueMappings::getInstance()->horizontalFacingCoral, fn(HorizontalFacing $b) => $b->getFacing(), fn(HorizontalFacing $b, HorizontalFacingOption $v) => $b->setFacing($v)),
+ ])
+ );
+ }
+
+ private static function registerCopperMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::COPPER_BULB())
+ ->idComponents([...$commonProperties->copperIdPrefixes, "copper_bulb"])
+ ->properties([
+ $commonProperties->lit,
+ new BoolProperty(StateNames::POWERED_BIT, fn(PoweredByRedstone $b) => $b->isPowered(), fn(PoweredByRedstone $b, bool $v) => $b->setPowered($v)),
+ ])
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::COPPER())
+ ->idComponents([
+ ...$commonProperties->copperIdPrefixes,
+ "copper",
+ //HACK: the non-waxed, non-oxidised variant has a _block suffix, but none of the others do
+ new BoolFromStringProperty("bruhhhh", "", "_block", fn(Copper $b) => !$b->isWaxed() && $b->getOxidation() === CopperOxidation::NONE, fn() => null)
+ ])
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::CHISELED_COPPER())->idComponents([...$commonProperties->copperIdPrefixes, "chiseled_copper"]));
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::COPPER_GRATE())->idComponents([...$commonProperties->copperIdPrefixes, "copper_grate"]));
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::CUT_COPPER())->idComponents([...$commonProperties->copperIdPrefixes, "cut_copper"]));
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::CUT_COPPER_STAIRS())
+ ->idComponents([...$commonProperties->copperIdPrefixes, "cut_copper_stairs"])
+ ->properties($commonProperties->stairProperties)
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::COPPER_TRAPDOOR())
+ ->idComponents([...$commonProperties->copperIdPrefixes, "copper_trapdoor"])
+ ->properties($commonProperties->trapdoorProperties)
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::COPPER_DOOR())
+ ->idComponents([...$commonProperties->copperIdPrefixes, "copper_door"])
+ ->properties($commonProperties->doorProperties)
+ );
+
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::CUT_COPPER_SLAB())
+ ->idComponents([
+ ...$commonProperties->copperIdPrefixes,
+ $commonProperties->slabIdInfix,
+ "cut_copper_slab"
+ ])
+ ->properties([$commonProperties->slabPositionProperty])
+ );
+ }
+
+ private static function registerFlattenedEnumMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ //A
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::ANVIL())
+ ->idComponents([
+ new ValueFromStringProperty("id", IntFromRawStateMap::string([
+ 0 => Ids::ANVIL,
+ 1 => Ids::CHIPPED_ANVIL,
+ 2 => Ids::DAMAGED_ANVIL,
+ ]), fn(Anvil $b) => $b->getDamage(), fn(Anvil $b, int $v) => $b->setDamage($v))
+ ])
+ ->properties([$commonProperties->horizontalFacingCardinal])
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::AMETHYST_CLUSTER())
+ ->idComponents([
+ new ValueFromStringProperty("id", IntFromRawStateMap::string([
+ AmethystCluster::STAGE_SMALL_BUD => Ids::SMALL_AMETHYST_BUD,
+ AmethystCluster::STAGE_MEDIUM_BUD => Ids::MEDIUM_AMETHYST_BUD,
+ AmethystCluster::STAGE_LARGE_BUD => Ids::LARGE_AMETHYST_BUD,
+ AmethystCluster::STAGE_CLUSTER => Ids::AMETHYST_CLUSTER
+ ]), fn(AmethystCluster $b) => $b->getStage(), fn(AmethystCluster $b, int $v) => $b->setStage($v))
+ ])
+ ->properties([$commonProperties->blockFace])
+ );
+
+ //C
+ //This one is a special offender :<
+ //I have no idea why this only has 3 IDs - there are 4 in Java and 4 visually distinct states in Bedrock
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::CAVE_VINES())
+ ->idComponents([
+ "minecraft:cave_vines",
+ new ValueFromStringProperty(
+ "variant",
+ EnumFromRawStateMap::string(FlattenedCaveVinesVariant::class, fn(FlattenedCaveVinesVariant $case) => $case->value),
+ fn(CaveVines $b) => $b->hasBerries() ?
+ ($b->isHead() ?
+ FlattenedCaveVinesVariant::HEAD_WITH_BERRIES :
+ FlattenedCaveVinesVariant::BODY_WITH_BERRIES) :
+ FlattenedCaveVinesVariant::NO_BERRIES,
+ fn(CaveVines $b, FlattenedCaveVinesVariant $v) => match($v){
+ FlattenedCaveVinesVariant::HEAD_WITH_BERRIES => $b->setBerries(true)->setHead(true),
+ FlattenedCaveVinesVariant::BODY_WITH_BERRIES => $b->setBerries(true)->setHead(false),
+ FlattenedCaveVinesVariant::NO_BERRIES => $b->setBerries(false)->setHead(false), //assume this isn't a head, since we don't have enough information
+ }
+ )
+ ])
+ ->properties([
+ new IntProperty(StateNames::GROWING_PLANT_AGE, 0, 25, fn(CaveVines $b) => $b->getAge(), fn(CaveVines $b, int $v) => $b->setAge($v)),
+ ])
+ );
+
+ //D
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::DIRT())
+ ->idComponents([
+ new ValueFromStringProperty("id", EnumFromRawStateMap::string(DirtType::class, fn(DirtType $case) => match ($case) {
+ DirtType::NORMAL => Ids::DIRT,
+ DirtType::COARSE => Ids::COARSE_DIRT,
+ DirtType::ROOTED => Ids::DIRT_WITH_ROOTS,
+ }), fn(Dirt $b) => $b->getDirtType(), fn(Dirt $b, DirtType $v) => $b->setDirtType($v))
+ ])
+ );
+
+ //F
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::FROGLIGHT())
+ ->idComponents([
+ new ValueFromStringProperty("id", ValueMappings::getInstance()->froglightType, fn(Froglight $b) => $b->getFroglightType(), fn(Froglight $b, FroglightType $v) => $b->setFroglightType($v)),
+ ])
+ ->properties([$commonProperties->pillarAxis])
+ );
+
+ //L
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::LIGHT())
+ ->idComponents([
+ "minecraft:light_block_",
+ //this is a bit shit but it's easier than adapting IntProperty to support flattening :D
+ new ValueFromStringProperty(
+ "light_level",
+ IntFromRawStateMap::string(array_map(strval(...), range(0, 15))),
+ fn(Light $b) => $b->getLightLevel(),
+ fn(Light $b, int $v) => $b->setLightLevel($v)
+ )
+ ])
+ );
+
+ //M
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::MOB_HEAD())
+ ->idComponents([
+ new ValueFromStringProperty("id", ValueMappings::getInstance()->mobHeadType, fn(MobHead $b) => $b->getMobHeadType(), fn(MobHead $b, MobHeadType $v) => $b->setMobHeadType($v)),
+ ])
+ ->properties([
+ new ValueFromIntProperty(StateNames::FACING_DIRECTION, ValueMappings::getInstance()->facingExceptDown, fn(MobHead $b) => $b->getFacing()->value, fn(MobHead $b, int $v) => $b->setFacing(Facing::from($v)))
+ ])
+ );
+
+ foreach([
+ [Blocks::LAVA(), "lava"],
+ [Blocks::WATER(), "water"]
+ ] as [$block, $idSuffix]){
+ $reg->mapFlattenedId(FlattenedIdModel::create($block)
+ ->idComponents([...$commonProperties->liquidIdPrefixes, $idSuffix])
+ ->properties([$commonProperties->liquidData])
+ );
+ }
+ }
+
+ private static function registerFlattenedBoolMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ foreach([
+ [Blocks::BLAST_FURNACE(), "blast_furnace"],
+ [Blocks::FURNACE(), "furnace"],
+ [Blocks::SMOKER(), "smoker"]
+ ] as [$block, $idSuffix]){
+ $reg->mapFlattenedId(FlattenedIdModel::create($block)
+ ->idComponents([...$commonProperties->furnaceIdPrefixes, $idSuffix])
+ ->properties([$commonProperties->horizontalFacingCardinal])
+ );
+ }
+
+ foreach([
+ [Blocks::REDSTONE_LAMP(), "redstone_lamp"],
+ [Blocks::REDSTONE_ORE(), "redstone_ore"],
+ [Blocks::DEEPSLATE_REDSTONE_ORE(), "deepslate_redstone_ore"]
+ ] as [$block, $idSuffix]){
+ $reg->mapFlattenedId(FlattenedIdModel::create($block)->idComponents(["minecraft:", $commonProperties->litIdInfix, $idSuffix]));
+ }
+
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::DAYLIGHT_SENSOR())
+ ->idComponents([
+ "minecraft:daylight_detector",
+ new BoolFromStringProperty("inverted", "", "_inverted", fn(DaylightSensor $b) => $b->isInverted(), fn(DaylightSensor $b, bool $v) => $b->setInverted($v))
+ ])
+ ->properties([$commonProperties->analogRedstoneSignal])
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::REDSTONE_REPEATER())
+ ->idComponents([
+ "minecraft:",
+ new BoolFromStringProperty("powered", "un", "", fn(RedstoneRepeater $b) => $b->isPowered(), fn(RedstoneRepeater $b, bool $v) => $b->setPowered($v)),
+ "powered_repeater"
+ ])
+ ->properties([
+ $commonProperties->horizontalFacingCardinal,
+ new IntProperty(StateNames::REPEATER_DELAY, 0, 3, fn(RedstoneRepeater $b) => $b->getDelay(), fn(RedstoneRepeater $b, int $v) => $b->setDelay($v), offset: 1),
+ ])
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::REDSTONE_COMPARATOR())
+ ->idComponents([
+ "minecraft:",
+ //this property also appears in the state, so we ignore it in the ID
+ //this is baked here purely to keep minecraft happy
+ new BoolFromStringProperty("dummy_powered", "un", "", fn(RedstoneComparator $b) => $b->isPowered(), fn() => null),
+ "powered_comparator"
+ ])
+ ->properties([
+ $commonProperties->horizontalFacingCardinal,
+ new BoolProperty(StateNames::OUTPUT_LIT_BIT, fn(RedstoneComparator $b) => $b->isPowered(), fn(RedstoneComparator $b, bool $v) => $b->setPowered($v)),
+ new BoolProperty(StateNames::OUTPUT_SUBTRACT_BIT, fn(RedstoneComparator $b) => $b->isSubtractMode(), fn(RedstoneComparator $b, bool $v) => $b->setSubtractMode($v)),
+ ])
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::REDSTONE_TORCH())
+ ->idComponents([
+ "minecraft:",
+ new BoolFromStringProperty("lit", "unlit_", "", fn(RedstoneTorch $b) => $b->isLit(), fn(RedstoneTorch $b, bool $v) => $b->setLit($v)),
+ "redstone_torch"
+ ])
+ ->properties([$commonProperties->torchFacing])
+ );
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::SPONGE())->idComponents([
+ "minecraft:",
+ new BoolFromStringProperty("wet", "", "wet_", fn(Sponge $b) => $b->isWet(), fn(Sponge $b, bool $v) => $b->setWet($v)),
+ "sponge"
+ ]));
+ $reg->mapFlattenedId(FlattenedIdModel::create(Blocks::TNT())
+ ->idComponents([
+ "minecraft:",
+ new BoolFromStringProperty("underwater", "", "underwater_", fn(TNT $b) => $b->worksUnderwater(), fn(TNT $b, bool $v) => $b->setWorksUnderwater($v)),
+ "tnt"
+ ])
+ ->properties([
+ new BoolProperty(StateNames::EXPLODE_BIT, fn(TNT $b) => $b->isUnstable(), fn(TNT $b, bool $v) => $b->setUnstable($v)),
+ ])
+ );
+ }
+
+ private static function registerStoneLikeSlabMappings(BlockSerializerDeserializerRegistrar $reg) : void{
+ $reg->mapSlab(Blocks::ANDESITE_SLAB(), "andesite");
+ $reg->mapSlab(Blocks::BLACKSTONE_SLAB(), "blackstone");
+ $reg->mapSlab(Blocks::BRICK_SLAB(), "brick");
+ $reg->mapSlab(Blocks::COBBLED_DEEPSLATE_SLAB(), "cobbled_deepslate");
+ $reg->mapSlab(Blocks::COBBLESTONE_SLAB(), "cobblestone");
+ $reg->mapSlab(Blocks::CUT_RED_SANDSTONE_SLAB(), "cut_red_sandstone");
+ $reg->mapSlab(Blocks::CUT_SANDSTONE_SLAB(), "cut_sandstone");
+ $reg->mapSlab(Blocks::DARK_PRISMARINE_SLAB(), "dark_prismarine");
+ $reg->mapSlab(Blocks::DEEPSLATE_BRICK_SLAB(), "deepslate_brick");
+ $reg->mapSlab(Blocks::DEEPSLATE_TILE_SLAB(), "deepslate_tile");
+ $reg->mapSlab(Blocks::DIORITE_SLAB(), "diorite");
+ $reg->mapSlab(Blocks::END_STONE_BRICK_SLAB(), "end_stone_brick");
+ $reg->mapSlab(Blocks::FAKE_WOODEN_SLAB(), "petrified_oak");
+ $reg->mapSlab(Blocks::GRANITE_SLAB(), "granite");
+ $reg->mapSlab(Blocks::MOSSY_COBBLESTONE_SLAB(), "mossy_cobblestone");
+ $reg->mapSlab(Blocks::MOSSY_STONE_BRICK_SLAB(), "mossy_stone_brick");
+ $reg->mapSlab(Blocks::MUD_BRICK_SLAB(), "mud_brick");
+ $reg->mapSlab(Blocks::NETHER_BRICK_SLAB(), "nether_brick");
+ $reg->mapSlab(Blocks::POLISHED_ANDESITE_SLAB(), "polished_andesite");
+ $reg->mapSlab(Blocks::POLISHED_BLACKSTONE_BRICK_SLAB(), "polished_blackstone_brick");
+ $reg->mapSlab(Blocks::POLISHED_BLACKSTONE_SLAB(), "polished_blackstone");
+ $reg->mapSlab(Blocks::POLISHED_DEEPSLATE_SLAB(), "polished_deepslate");
+ $reg->mapSlab(Blocks::POLISHED_DIORITE_SLAB(), "polished_diorite");
+ $reg->mapSlab(Blocks::POLISHED_GRANITE_SLAB(), "polished_granite");
+ $reg->mapSlab(Blocks::POLISHED_TUFF_SLAB(), "polished_tuff");
+ $reg->mapSlab(Blocks::PRISMARINE_BRICKS_SLAB(), "prismarine_brick");
+ $reg->mapSlab(Blocks::PRISMARINE_SLAB(), "prismarine");
+ $reg->mapSlab(Blocks::PURPUR_SLAB(), "purpur");
+ $reg->mapSlab(Blocks::QUARTZ_SLAB(), "quartz");
+ $reg->mapSlab(Blocks::RED_NETHER_BRICK_SLAB(), "red_nether_brick");
+ $reg->mapSlab(Blocks::RED_SANDSTONE_SLAB(), "red_sandstone");
+ $reg->mapSlab(Blocks::RESIN_BRICK_SLAB(), "resin_brick");
+ $reg->mapSlab(Blocks::SANDSTONE_SLAB(), "sandstone");
+ $reg->mapSlab(Blocks::SMOOTH_QUARTZ_SLAB(), "smooth_quartz");
+ $reg->mapSlab(Blocks::SMOOTH_RED_SANDSTONE_SLAB(), "smooth_red_sandstone");
+ $reg->mapSlab(Blocks::SMOOTH_SANDSTONE_SLAB(), "smooth_sandstone");
+ $reg->mapSlab(Blocks::SMOOTH_STONE_SLAB(), "smooth_stone");
+ $reg->mapSlab(Blocks::STONE_BRICK_SLAB(), "stone_brick");
+ $reg->mapSlab(Blocks::STONE_SLAB(), "normal_stone");
+ $reg->mapSlab(Blocks::TUFF_BRICK_SLAB(), "tuff_brick");
+ $reg->mapSlab(Blocks::TUFF_SLAB(), "tuff");
+ }
+
+ private static function registerStoneLikeStairMappings(BlockSerializerDeserializerRegistrar $reg) : void{
+ $reg->mapStairs(Blocks::ANDESITE_STAIRS(), Ids::ANDESITE_STAIRS);
+ $reg->mapStairs(Blocks::BLACKSTONE_STAIRS(), Ids::BLACKSTONE_STAIRS);
+ $reg->mapStairs(Blocks::BRICK_STAIRS(), Ids::BRICK_STAIRS);
+ $reg->mapStairs(Blocks::COBBLED_DEEPSLATE_STAIRS(), Ids::COBBLED_DEEPSLATE_STAIRS);
+ $reg->mapStairs(Blocks::COBBLESTONE_STAIRS(), Ids::STONE_STAIRS);
+ $reg->mapStairs(Blocks::DARK_PRISMARINE_STAIRS(), Ids::DARK_PRISMARINE_STAIRS);
+ $reg->mapStairs(Blocks::DEEPSLATE_BRICK_STAIRS(), Ids::DEEPSLATE_BRICK_STAIRS);
+ $reg->mapStairs(Blocks::DEEPSLATE_TILE_STAIRS(), Ids::DEEPSLATE_TILE_STAIRS);
+ $reg->mapStairs(Blocks::DIORITE_STAIRS(), Ids::DIORITE_STAIRS);
+ $reg->mapStairs(Blocks::END_STONE_BRICK_STAIRS(), Ids::END_BRICK_STAIRS);
+ $reg->mapStairs(Blocks::GRANITE_STAIRS(), Ids::GRANITE_STAIRS);
+ $reg->mapStairs(Blocks::MOSSY_COBBLESTONE_STAIRS(), Ids::MOSSY_COBBLESTONE_STAIRS);
+ $reg->mapStairs(Blocks::MOSSY_STONE_BRICK_STAIRS(), Ids::MOSSY_STONE_BRICK_STAIRS);
+ $reg->mapStairs(Blocks::MUD_BRICK_STAIRS(), Ids::MUD_BRICK_STAIRS);
+ $reg->mapStairs(Blocks::NETHER_BRICK_STAIRS(), Ids::NETHER_BRICK_STAIRS);
+ $reg->mapStairs(Blocks::POLISHED_ANDESITE_STAIRS(), Ids::POLISHED_ANDESITE_STAIRS);
+ $reg->mapStairs(Blocks::POLISHED_BLACKSTONE_BRICK_STAIRS(), Ids::POLISHED_BLACKSTONE_BRICK_STAIRS);
+ $reg->mapStairs(Blocks::POLISHED_BLACKSTONE_STAIRS(), Ids::POLISHED_BLACKSTONE_STAIRS);
+ $reg->mapStairs(Blocks::POLISHED_DEEPSLATE_STAIRS(), Ids::POLISHED_DEEPSLATE_STAIRS);
+ $reg->mapStairs(Blocks::POLISHED_DIORITE_STAIRS(), Ids::POLISHED_DIORITE_STAIRS);
+ $reg->mapStairs(Blocks::POLISHED_GRANITE_STAIRS(), Ids::POLISHED_GRANITE_STAIRS);
+ $reg->mapStairs(Blocks::POLISHED_TUFF_STAIRS(), Ids::POLISHED_TUFF_STAIRS);
+ $reg->mapStairs(Blocks::PRISMARINE_BRICKS_STAIRS(), Ids::PRISMARINE_BRICKS_STAIRS);
+ $reg->mapStairs(Blocks::PRISMARINE_STAIRS(), Ids::PRISMARINE_STAIRS);
+ $reg->mapStairs(Blocks::PURPUR_STAIRS(), Ids::PURPUR_STAIRS);
+ $reg->mapStairs(Blocks::QUARTZ_STAIRS(), Ids::QUARTZ_STAIRS);
+ $reg->mapStairs(Blocks::RED_NETHER_BRICK_STAIRS(), Ids::RED_NETHER_BRICK_STAIRS);
+ $reg->mapStairs(Blocks::RED_SANDSTONE_STAIRS(), Ids::RED_SANDSTONE_STAIRS);
+ $reg->mapStairs(Blocks::RESIN_BRICK_STAIRS(), Ids::RESIN_BRICK_STAIRS);
+ $reg->mapStairs(Blocks::SANDSTONE_STAIRS(), Ids::SANDSTONE_STAIRS);
+ $reg->mapStairs(Blocks::SMOOTH_QUARTZ_STAIRS(), Ids::SMOOTH_QUARTZ_STAIRS);
+ $reg->mapStairs(Blocks::SMOOTH_RED_SANDSTONE_STAIRS(), Ids::SMOOTH_RED_SANDSTONE_STAIRS);
+ $reg->mapStairs(Blocks::SMOOTH_SANDSTONE_STAIRS(), Ids::SMOOTH_SANDSTONE_STAIRS);
+ $reg->mapStairs(Blocks::STONE_BRICK_STAIRS(), Ids::STONE_BRICK_STAIRS);
+ $reg->mapStairs(Blocks::STONE_STAIRS(), Ids::NORMAL_STONE_STAIRS);
+ $reg->mapStairs(Blocks::TUFF_BRICK_STAIRS(), Ids::TUFF_BRICK_STAIRS);
+ $reg->mapStairs(Blocks::TUFF_STAIRS(), Ids::TUFF_STAIRS);
+ }
+
+ private static function registerStoneLikeWallMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ foreach([
+ Ids::ANDESITE_WALL => Blocks::ANDESITE_WALL(),
+ Ids::BLACKSTONE_WALL => Blocks::BLACKSTONE_WALL(),
+ Ids::BRICK_WALL => Blocks::BRICK_WALL(),
+ Ids::COBBLED_DEEPSLATE_WALL => Blocks::COBBLED_DEEPSLATE_WALL(),
+ Ids::COBBLESTONE_WALL => Blocks::COBBLESTONE_WALL(),
+ Ids::DEEPSLATE_BRICK_WALL => Blocks::DEEPSLATE_BRICK_WALL(),
+ Ids::DEEPSLATE_TILE_WALL => Blocks::DEEPSLATE_TILE_WALL(),
+ Ids::DIORITE_WALL => Blocks::DIORITE_WALL(),
+ Ids::END_STONE_BRICK_WALL => Blocks::END_STONE_BRICK_WALL(),
+ Ids::GRANITE_WALL => Blocks::GRANITE_WALL(),
+ Ids::MOSSY_COBBLESTONE_WALL => Blocks::MOSSY_COBBLESTONE_WALL(),
+ Ids::MOSSY_STONE_BRICK_WALL => Blocks::MOSSY_STONE_BRICK_WALL(),
+ Ids::MUD_BRICK_WALL => Blocks::MUD_BRICK_WALL(),
+ Ids::NETHER_BRICK_WALL => Blocks::NETHER_BRICK_WALL(),
+ Ids::POLISHED_BLACKSTONE_BRICK_WALL => Blocks::POLISHED_BLACKSTONE_BRICK_WALL(),
+ Ids::POLISHED_BLACKSTONE_WALL => Blocks::POLISHED_BLACKSTONE_WALL(),
+ Ids::POLISHED_DEEPSLATE_WALL => Blocks::POLISHED_DEEPSLATE_WALL(),
+ Ids::POLISHED_TUFF_WALL => Blocks::POLISHED_TUFF_WALL(),
+ Ids::PRISMARINE_WALL => Blocks::PRISMARINE_WALL(),
+ Ids::RED_NETHER_BRICK_WALL => Blocks::RED_NETHER_BRICK_WALL(),
+ Ids::RED_SANDSTONE_WALL => Blocks::RED_SANDSTONE_WALL(),
+ Ids::RESIN_BRICK_WALL => Blocks::RESIN_BRICK_WALL(),
+ Ids::SANDSTONE_WALL => Blocks::SANDSTONE_WALL(),
+ Ids::STONE_BRICK_WALL => Blocks::STONE_BRICK_WALL(),
+ Ids::TUFF_BRICK_WALL => Blocks::TUFF_BRICK_WALL(),
+ Ids::TUFF_WALL => Blocks::TUFF_WALL()
+ ] as $id => $block){
+ $reg->mapModel(Model::create($block, $id)->properties($commonProperties->wallProperties));
+ }
+ }
+
+ private static function registerWoodMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ //buttons
+ foreach([
+ [Blocks::ACACIA_BUTTON(), Ids::ACACIA_BUTTON],
+ [Blocks::BIRCH_BUTTON(), Ids::BIRCH_BUTTON],
+ [Blocks::CHERRY_BUTTON(), Ids::CHERRY_BUTTON],
+ [Blocks::CRIMSON_BUTTON(), Ids::CRIMSON_BUTTON],
+ [Blocks::DARK_OAK_BUTTON(), Ids::DARK_OAK_BUTTON],
+ [Blocks::JUNGLE_BUTTON(), Ids::JUNGLE_BUTTON],
+ [Blocks::MANGROVE_BUTTON(), Ids::MANGROVE_BUTTON],
+ [Blocks::OAK_BUTTON(), Ids::WOODEN_BUTTON],
+ [Blocks::PALE_OAK_BUTTON(), Ids::PALE_OAK_BUTTON],
+ [Blocks::SPRUCE_BUTTON(), Ids::SPRUCE_BUTTON],
+ [Blocks::WARPED_BUTTON(), Ids::WARPED_BUTTON]
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties($commonProperties->buttonProperties));
+ }
+
+ //doors
+ foreach([
+ [Blocks::ACACIA_DOOR(), Ids::ACACIA_DOOR],
+ [Blocks::BIRCH_DOOR(), Ids::BIRCH_DOOR],
+ [Blocks::CHERRY_DOOR(), Ids::CHERRY_DOOR],
+ [Blocks::CRIMSON_DOOR(), Ids::CRIMSON_DOOR],
+ [Blocks::DARK_OAK_DOOR(), Ids::DARK_OAK_DOOR],
+ [Blocks::JUNGLE_DOOR(), Ids::JUNGLE_DOOR],
+ [Blocks::MANGROVE_DOOR(), Ids::MANGROVE_DOOR],
+ [Blocks::OAK_DOOR(), Ids::WOODEN_DOOR],
+ [Blocks::PALE_OAK_DOOR(), Ids::PALE_OAK_DOOR],
+ [Blocks::SPRUCE_DOOR(), Ids::SPRUCE_DOOR],
+ [Blocks::WARPED_DOOR(), Ids::WARPED_DOOR]
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties($commonProperties->doorProperties));
+ }
+
+ //fences
+ foreach([
+ [Blocks::ACACIA_FENCE(), Ids::ACACIA_FENCE],
+ [Blocks::BIRCH_FENCE(), Ids::BIRCH_FENCE],
+ [Blocks::CHERRY_FENCE(), Ids::CHERRY_FENCE],
+ [Blocks::DARK_OAK_FENCE(), Ids::DARK_OAK_FENCE],
+ [Blocks::JUNGLE_FENCE(), Ids::JUNGLE_FENCE],
+ [Blocks::MANGROVE_FENCE(), Ids::MANGROVE_FENCE],
+ [Blocks::OAK_FENCE(), Ids::OAK_FENCE],
+ [Blocks::PALE_OAK_FENCE(), Ids::PALE_OAK_FENCE],
+ [Blocks::SPRUCE_FENCE(), Ids::SPRUCE_FENCE],
+ [Blocks::CRIMSON_FENCE(), Ids::CRIMSON_FENCE],
+ [Blocks::WARPED_FENCE(), Ids::WARPED_FENCE]
+ ] as [$block, $id]){
+ $reg->mapSimple($block, $id);
+ }
+
+ foreach([
+ [Blocks::ACACIA_FENCE_GATE(), Ids::ACACIA_FENCE_GATE],
+ [Blocks::BIRCH_FENCE_GATE(), Ids::BIRCH_FENCE_GATE],
+ [Blocks::CHERRY_FENCE_GATE(), Ids::CHERRY_FENCE_GATE],
+ [Blocks::DARK_OAK_FENCE_GATE(), Ids::DARK_OAK_FENCE_GATE],
+ [Blocks::JUNGLE_FENCE_GATE(), Ids::JUNGLE_FENCE_GATE],
+ [Blocks::MANGROVE_FENCE_GATE(), Ids::MANGROVE_FENCE_GATE],
+ [Blocks::OAK_FENCE_GATE(), Ids::FENCE_GATE],
+ [Blocks::PALE_OAK_FENCE_GATE(), Ids::PALE_OAK_FENCE_GATE],
+ [Blocks::SPRUCE_FENCE_GATE(), Ids::SPRUCE_FENCE_GATE],
+ [Blocks::CRIMSON_FENCE_GATE(), Ids::CRIMSON_FENCE_GATE],
+ [Blocks::WARPED_FENCE_GATE(), Ids::WARPED_FENCE_GATE]
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties($commonProperties->fenceGateProperties));
+ }
+
+ foreach([
+ [Blocks::ACACIA_SIGN(), Ids::ACACIA_STANDING_SIGN],
+ [Blocks::BIRCH_SIGN(), Ids::BIRCH_STANDING_SIGN],
+ [Blocks::CHERRY_SIGN(), Ids::CHERRY_STANDING_SIGN],
+ [Blocks::DARK_OAK_SIGN(), Ids::DARKOAK_STANDING_SIGN],
+ [Blocks::JUNGLE_SIGN(), Ids::JUNGLE_STANDING_SIGN],
+ [Blocks::MANGROVE_SIGN(), Ids::MANGROVE_STANDING_SIGN],
+ [Blocks::OAK_SIGN(), Ids::STANDING_SIGN],
+ [Blocks::PALE_OAK_SIGN(), Ids::PALE_OAK_STANDING_SIGN],
+ [Blocks::SPRUCE_SIGN(), Ids::SPRUCE_STANDING_SIGN],
+ [Blocks::CRIMSON_SIGN(), Ids::CRIMSON_STANDING_SIGN],
+ [Blocks::WARPED_SIGN(), Ids::WARPED_STANDING_SIGN]
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties([$commonProperties->floorSignLikeRotation]));
+ }
+
+ //logs
+ foreach([
+ [Blocks::ACACIA_LOG(), "acacia_log"],
+ [Blocks::BIRCH_LOG(), "birch_log"],
+ [Blocks::CHERRY_LOG(), "cherry_log"],
+ [Blocks::DARK_OAK_LOG(), "dark_oak_log"],
+ [Blocks::JUNGLE_LOG(), "jungle_log"],
+ [Blocks::MANGROVE_LOG(), "mangrove_log"],
+ [Blocks::OAK_LOG(), "oak_log"],
+ [Blocks::PALE_OAK_LOG(), "pale_oak_log"],
+ [Blocks::SPRUCE_LOG(), "spruce_log"],
+ [Blocks::CRIMSON_STEM(), "crimson_stem"],
+ [Blocks::WARPED_STEM(), "warped_stem"],
+
+ //all-sided logs
+ [Blocks::ACACIA_WOOD(), "acacia_wood"],
+ [Blocks::BIRCH_WOOD(), "birch_wood"],
+ [Blocks::CHERRY_WOOD(), "cherry_wood"],
+ [Blocks::DARK_OAK_WOOD(), "dark_oak_wood"],
+ [Blocks::JUNGLE_WOOD(), "jungle_wood"],
+ [Blocks::MANGROVE_WOOD(), "mangrove_wood"],
+ [Blocks::OAK_WOOD(), "oak_wood"],
+ [Blocks::PALE_OAK_WOOD(), "pale_oak_wood"],
+ [Blocks::SPRUCE_WOOD(), "spruce_wood"],
+ [Blocks::CRIMSON_HYPHAE(), "crimson_hyphae"],
+ [Blocks::WARPED_HYPHAE(), "warped_hyphae"]
+ ] as [$block, $idSuffix]){
+ $reg->mapFlattenedId(FlattenedIdModel::create($block)
+ ->idComponents([...$commonProperties->woodIdPrefixes, $idSuffix])
+ ->properties([$commonProperties->pillarAxis])
+ );
+ }
+
+ //planks
+ foreach([
+ [Blocks::ACACIA_PLANKS(), Ids::ACACIA_PLANKS],
+ [Blocks::BIRCH_PLANKS(), Ids::BIRCH_PLANKS],
+ [Blocks::CHERRY_PLANKS(), Ids::CHERRY_PLANKS],
+ [Blocks::DARK_OAK_PLANKS(), Ids::DARK_OAK_PLANKS],
+ [Blocks::JUNGLE_PLANKS(), Ids::JUNGLE_PLANKS],
+ [Blocks::MANGROVE_PLANKS(), Ids::MANGROVE_PLANKS],
+ [Blocks::OAK_PLANKS(), Ids::OAK_PLANKS],
+ [Blocks::PALE_OAK_PLANKS(), Ids::PALE_OAK_PLANKS],
+ [Blocks::SPRUCE_PLANKS(), Ids::SPRUCE_PLANKS],
+ [Blocks::CRIMSON_PLANKS(), Ids::CRIMSON_PLANKS],
+ [Blocks::WARPED_PLANKS(), Ids::WARPED_PLANKS]
+ ] as [$block, $id]){
+ $reg->mapSimple($block, $id);
+ }
+
+ //pressure plates
+ foreach([
+ [Blocks::ACACIA_PRESSURE_PLATE(), Ids::ACACIA_PRESSURE_PLATE],
+ [Blocks::BIRCH_PRESSURE_PLATE(), Ids::BIRCH_PRESSURE_PLATE],
+ [Blocks::CHERRY_PRESSURE_PLATE(), Ids::CHERRY_PRESSURE_PLATE],
+ [Blocks::DARK_OAK_PRESSURE_PLATE(), Ids::DARK_OAK_PRESSURE_PLATE],
+ [Blocks::JUNGLE_PRESSURE_PLATE(), Ids::JUNGLE_PRESSURE_PLATE],
+ [Blocks::MANGROVE_PRESSURE_PLATE(), Ids::MANGROVE_PRESSURE_PLATE],
+ [Blocks::OAK_PRESSURE_PLATE(), Ids::WOODEN_PRESSURE_PLATE],
+ [Blocks::PALE_OAK_PRESSURE_PLATE(), Ids::PALE_OAK_PRESSURE_PLATE],
+ [Blocks::SPRUCE_PRESSURE_PLATE(), Ids::SPRUCE_PRESSURE_PLATE],
+ [Blocks::CRIMSON_PRESSURE_PLATE(), Ids::CRIMSON_PRESSURE_PLATE],
+ [Blocks::WARPED_PRESSURE_PLATE(), Ids::WARPED_PRESSURE_PLATE]
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties($commonProperties->simplePressurePlateProperties));
+ }
+
+ //slabs
+ foreach([
+ [Blocks::ACACIA_SLAB(), "acacia"],
+ [Blocks::BIRCH_SLAB(), "birch"],
+ [Blocks::CHERRY_SLAB(), "cherry"],
+ [Blocks::DARK_OAK_SLAB(), "dark_oak"],
+ [Blocks::JUNGLE_SLAB(), "jungle"],
+ [Blocks::MANGROVE_SLAB(), "mangrove"],
+ [Blocks::OAK_SLAB(), "oak"],
+ [Blocks::PALE_OAK_SLAB(), "pale_oak"],
+ [Blocks::SPRUCE_SLAB(), "spruce"],
+ [Blocks::CRIMSON_SLAB(), "crimson"],
+ [Blocks::WARPED_SLAB(), "warped"]
+ ] as [$block, $type]){
+ $reg->mapSlab($block, $type);
+ }
+
+ //stairs
+ foreach([
+ [Blocks::ACACIA_STAIRS(), Ids::ACACIA_STAIRS],
+ [Blocks::BIRCH_STAIRS(), Ids::BIRCH_STAIRS],
+ [Blocks::CHERRY_STAIRS(), Ids::CHERRY_STAIRS],
+ [Blocks::DARK_OAK_STAIRS(), Ids::DARK_OAK_STAIRS],
+ [Blocks::JUNGLE_STAIRS(), Ids::JUNGLE_STAIRS],
+ [Blocks::MANGROVE_STAIRS(), Ids::MANGROVE_STAIRS],
+ [Blocks::OAK_STAIRS(), Ids::OAK_STAIRS],
+ [Blocks::PALE_OAK_STAIRS(), Ids::PALE_OAK_STAIRS],
+ [Blocks::SPRUCE_STAIRS(), Ids::SPRUCE_STAIRS],
+ [Blocks::CRIMSON_STAIRS(), Ids::CRIMSON_STAIRS],
+ [Blocks::WARPED_STAIRS(), Ids::WARPED_STAIRS]
+ ] as [$block, $id]){
+ $reg->mapStairs($block, $id);
+ }
+
+ //trapdoors
+ foreach([
+ [Blocks::ACACIA_TRAPDOOR(), Ids::ACACIA_TRAPDOOR],
+ [Blocks::BIRCH_TRAPDOOR(), Ids::BIRCH_TRAPDOOR],
+ [Blocks::CHERRY_TRAPDOOR(), Ids::CHERRY_TRAPDOOR],
+ [Blocks::DARK_OAK_TRAPDOOR(), Ids::DARK_OAK_TRAPDOOR],
+ [Blocks::JUNGLE_TRAPDOOR(), Ids::JUNGLE_TRAPDOOR],
+ [Blocks::MANGROVE_TRAPDOOR(), Ids::MANGROVE_TRAPDOOR],
+ [Blocks::OAK_TRAPDOOR(), Ids::TRAPDOOR],
+ [Blocks::PALE_OAK_TRAPDOOR(), Ids::PALE_OAK_TRAPDOOR],
+ [Blocks::SPRUCE_TRAPDOOR(), Ids::SPRUCE_TRAPDOOR],
+ [Blocks::CRIMSON_TRAPDOOR(), Ids::CRIMSON_TRAPDOOR],
+ [Blocks::WARPED_TRAPDOOR(), Ids::WARPED_TRAPDOOR]
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties($commonProperties->trapdoorProperties));
+ }
+
+ //wall signs
+ foreach([
+ [Blocks::ACACIA_WALL_SIGN(), Ids::ACACIA_WALL_SIGN],
+ [Blocks::BIRCH_WALL_SIGN(), Ids::BIRCH_WALL_SIGN],
+ [Blocks::CHERRY_WALL_SIGN(), Ids::CHERRY_WALL_SIGN],
+ [Blocks::DARK_OAK_WALL_SIGN(), Ids::DARKOAK_WALL_SIGN],
+ [Blocks::JUNGLE_WALL_SIGN(), Ids::JUNGLE_WALL_SIGN],
+ [Blocks::MANGROVE_WALL_SIGN(), Ids::MANGROVE_WALL_SIGN],
+ [Blocks::OAK_WALL_SIGN(), Ids::WALL_SIGN],
+ [Blocks::PALE_OAK_WALL_SIGN(), Ids::PALE_OAK_WALL_SIGN],
+ [Blocks::SPRUCE_WALL_SIGN(), Ids::SPRUCE_WALL_SIGN],
+ [Blocks::CRIMSON_WALL_SIGN(), Ids::CRIMSON_WALL_SIGN],
+ [Blocks::WARPED_WALL_SIGN(), Ids::WARPED_WALL_SIGN]
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties([$commonProperties->horizontalFacingClassic]));
+ }
+ }
+
+ private static function registerTorchMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ foreach([
+ [Blocks::BLUE_TORCH(), Ids::COLORED_TORCH_BLUE],
+ [Blocks::GREEN_TORCH(), Ids::COLORED_TORCH_GREEN],
+ [Blocks::PURPLE_TORCH(), Ids::COLORED_TORCH_PURPLE],
+ [Blocks::RED_TORCH(), Ids::COLORED_TORCH_RED],
+ [Blocks::SOUL_TORCH(), Ids::SOUL_TORCH],
+ [Blocks::TORCH(), Ids::TORCH],
+ [Blocks::UNDERWATER_TORCH(), Ids::UNDERWATER_TORCH]
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties([$commonProperties->torchFacing]));
+ }
+ }
+
+ private static function registerChemistryMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ foreach([
+ [Blocks::COMPOUND_CREATOR(), Ids::COMPOUND_CREATOR],
+ [Blocks::ELEMENT_CONSTRUCTOR(), Ids::ELEMENT_CONSTRUCTOR],
+ [Blocks::LAB_TABLE(), Ids::LAB_TABLE],
+ [Blocks::MATERIAL_REDUCER(), Ids::MATERIAL_REDUCER],
+ ] as [$block, $id]){
+ $reg->mapModel(Model::create($block, $id)->properties([$commonProperties->horizontalFacingSWNEInverted]));
+ }
+ }
+
+ private static function register1to1CustomMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ //TODO: some of these have repeated accessor refs, we might be able to deduplicate them
+ //A
+ $reg->mapModel(Model::create(Blocks::ACTIVATOR_RAIL(), Ids::ACTIVATOR_RAIL)->properties([
+ new BoolProperty(StateNames::RAIL_DATA_BIT, fn(ActivatorRail $b) => $b->isPowered(), fn(ActivatorRail $b, bool $v) => $b->setPowered($v)),
+ $commonProperties->straightOnlyRailShape
+ ]));
+
+ //B
+ $reg->mapModel(Model::create(Blocks::BAMBOO(), Ids::BAMBOO)->properties([
+ new ValueFromStringProperty(StateNames::BAMBOO_LEAF_SIZE, ValueMappings::getInstance()->bambooLeafSize, fn(Bamboo $b) => $b->getLeafSize(), fn(Bamboo $b, int $v) => $b->setLeafSize($v)),
+ new BoolProperty(StateNames::AGE_BIT, fn(Bamboo $b) => $b->isReady(), fn(Bamboo $b, bool $v) => $b->setReady($v)),
+ new BoolFromStringProperty(StateNames::BAMBOO_STALK_THICKNESS, StringValues::BAMBOO_STALK_THICKNESS_THIN, StringValues::BAMBOO_STALK_THICKNESS_THICK, fn(Bamboo $b) => $b->isThick(), fn(Bamboo $b, bool $v) => $b->setThick($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::BAMBOO_SAPLING(), Ids::BAMBOO_SAPLING)->properties([
+ new BoolProperty(StateNames::AGE_BIT, fn(BambooSapling $b) => $b->isReady(), fn(BambooSapling $b, bool $v) => $b->setReady($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::BANNER(), Ids::STANDING_BANNER)->properties([$commonProperties->floorSignLikeRotation]));
+ $reg->mapModel(Model::create(Blocks::BARREL(), Ids::BARREL)->properties([
+ $commonProperties->anyFacingClassic,
+ new BoolProperty(StateNames::OPEN_BIT, fn(Barrel $b) => $b->isOpen(), fn(Barrel $b, bool $v) => $b->setOpen($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::BASALT(), Ids::BASALT)->properties([$commonProperties->pillarAxis]));
+ $reg->mapModel(Model::create(Blocks::BED(), Ids::BED)->properties([
+ new BoolProperty(StateNames::HEAD_PIECE_BIT, fn(Bed $b) => $b->isHeadPart(), fn(Bed $b, bool $v) => $b->setHead($v)),
+ new BoolProperty(StateNames::OCCUPIED_BIT, fn(Bed $b) => $b->isOccupied(), fn(Bed $b, bool $v) => $b->setOccupied($v)),
+ $commonProperties->horizontalFacingSWNE
+ ]));
+ $reg->mapModel(Model::create(Blocks::BEDROCK(), Ids::BEDROCK)->properties([
+ new BoolProperty(StateNames::INFINIBURN_BIT, fn(Bedrock $b) => $b->burnsForever(), fn(Bedrock $b, bool $v) => $b->setBurnsForever($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::BELL(), Ids::BELL)->properties([
+ BoolProperty::unused(StateNames::TOGGLE_BIT, false),
+ new ValueFromStringProperty(StateNames::ATTACHMENT, ValueMappings::getInstance()->bellAttachmentType, fn(Bell $b) => $b->getAttachmentType(), fn(Bell $b, BellAttachmentType $v) => $b->setAttachmentType($v)),
+ $commonProperties->horizontalFacingSWNE
+ ]));
+ $reg->mapModel(Model::create(Blocks::BONE_BLOCK(), Ids::BONE_BLOCK)->properties([
+ IntProperty::unused(StateNames::DEPRECATED, 0),
+ $commonProperties->pillarAxis
+ ]));
+
+ $reg->mapModel(Model::create(Blocks::BREWING_STAND(), Ids::BREWING_STAND)->properties(array_map(fn(BrewingStandSlot $slot) => new BoolProperty(match ($slot) {
+ BrewingStandSlot::EAST => StateNames::BREWING_STAND_SLOT_A_BIT,
+ BrewingStandSlot::SOUTHWEST => StateNames::BREWING_STAND_SLOT_B_BIT,
+ BrewingStandSlot::NORTHWEST => StateNames::BREWING_STAND_SLOT_C_BIT
+ }, fn(BrewingStand $b) => $b->hasSlot($slot), fn(BrewingStand $b, bool $v) => $b->setSlot($slot, $v)), BrewingStandSlot::cases())));
+
+ //C
+ $reg->mapModel(Model::create(Blocks::CACTUS(), Ids::CACTUS)->properties([
+ new IntProperty(StateNames::AGE, 0, 15, fn(Cactus $b) => $b->getAge(), fn(Cactus $b, int $v) => $b->setAge($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::CAKE(), Ids::CAKE)->properties([
+ new IntProperty(StateNames::BITE_COUNTER, 0, 6, fn(Cake $b) => $b->getBites(), fn(Cake $b, int $v) => $b->setBites($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::CAMPFIRE(), Ids::CAMPFIRE)->properties($commonProperties->campfireProperties));
+ $reg->mapModel(Model::create(Blocks::CARVED_PUMPKIN(), Ids::CARVED_PUMPKIN)->properties([
+ $commonProperties->horizontalFacingCardinal
+ ]));
+ $reg->mapModel(Model::create(Blocks::CHAIN(), Ids::CHAIN)->properties([$commonProperties->pillarAxis]));
+ $reg->mapModel(Model::create(Blocks::CHISELED_BOOKSHELF(), Ids::CHISELED_BOOKSHELF)->properties([
+ $commonProperties->horizontalFacingSWNE,
+ new ValueSetFromIntProperty(
+ StateNames::BOOKS_STORED,
+ EnumFromRawStateMap::int(ChiseledBookshelfSlot::class, fn(ChiseledBookshelfSlot $case) => match($case){
+ //these are (currently) the same as the internal values, but it's best not to rely on those in case Mojang mess with the flags
+ ChiseledBookshelfSlot::TOP_LEFT => 1 << 0,
+ ChiseledBookshelfSlot::TOP_MIDDLE => 1 << 1,
+ ChiseledBookshelfSlot::TOP_RIGHT => 1 << 2,
+ ChiseledBookshelfSlot::BOTTOM_LEFT => 1 << 3,
+ ChiseledBookshelfSlot::BOTTOM_MIDDLE => 1 << 4,
+ ChiseledBookshelfSlot::BOTTOM_RIGHT => 1 << 5
+ }),
+ fn(ChiseledBookshelf $b) => $b->getSlots(),
+ fn(ChiseledBookshelf $b, array $v) => $b->setSlots($v)
+ )
+ ]));
+ $reg->mapModel(Model::create(Blocks::CHISELED_QUARTZ(), Ids::CHISELED_QUARTZ_BLOCK)->properties([$commonProperties->pillarAxis]));
+ $reg->mapModel(Model::create(Blocks::CHEST(), Ids::CHEST)->properties([$commonProperties->horizontalFacingCardinal]));
+ $reg->mapModel(Model::create(Blocks::CHORUS_FLOWER(), Ids::CHORUS_FLOWER)->properties([
+ new IntProperty(StateNames::AGE, ChorusFlower::MIN_AGE, ChorusFlower::MAX_AGE, fn(ChorusFlower $b) => $b->getAge(), fn(ChorusFlower $b, int $v) => $b->setAge($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::COCOA_POD(), Ids::COCOA)->properties([
+ new IntProperty(StateNames::AGE, 0, 2, fn(CocoaBlock $b) => $b->getAge(), fn(CocoaBlock $b, int $v) => $b->setAge($v)),
+ $commonProperties->horizontalFacingSWNEInverted
+ ]));
+
+ //D
+ $reg->mapModel(Model::create(Blocks::DEEPSLATE(), Ids::DEEPSLATE)->properties([$commonProperties->pillarAxis]));
+ $reg->mapModel(Model::create(Blocks::DETECTOR_RAIL(), Ids::DETECTOR_RAIL)->properties([
+ new BoolProperty(StateNames::RAIL_DATA_BIT, fn(DetectorRail $b) => $b->isActivated(), fn(DetectorRail $b, bool $v) => $b->setActivated($v)),
+ $commonProperties->straightOnlyRailShape
+ ]));
+
+ //E
+ $reg->mapModel(Model::create(Blocks::ENDER_CHEST(), Ids::ENDER_CHEST)->properties([$commonProperties->horizontalFacingCardinal]));
+ $reg->mapModel(Model::create(Blocks::END_PORTAL_FRAME(), Ids::END_PORTAL_FRAME)->properties([
+ new BoolProperty(StateNames::END_PORTAL_EYE_BIT, fn(EndPortalFrame $b) => $b->hasEye(), fn(EndPortalFrame $b, bool $v) => $b->setEye($v)),
+ $commonProperties->horizontalFacingCardinal
+ ]));
+ $reg->mapModel(Model::create(Blocks::END_ROD(), Ids::END_ROD)->properties([
+ new ValueFromIntProperty(StateNames::FACING_DIRECTION, ValueMappings::getInstance()->facingEndRod, fn(EndRod $b) => $b->getFacing(), fn(EndRod $b, Facing $v) => $b->setFacing($v)),
+ ]));
+
+ //F
+ $reg->mapModel(Model::create(Blocks::FARMLAND(), Ids::FARMLAND)->properties([
+ new IntProperty(StateNames::MOISTURIZED_AMOUNT, 0, 7, fn(Farmland $b) => $b->getWetness(), fn(Farmland $b, int $v) => $b->setWetness($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::FIRE(), Ids::FIRE)->properties([
+ new IntProperty(StateNames::AGE, 0, 15, fn(Fire $b) => $b->getAge(), fn(Fire $b, int $v) => $b->setAge($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::FLOWER_POT(), Ids::FLOWER_POT)->properties([
+ BoolProperty::unused(StateNames::UPDATE_BIT, false)
+ ]));
+ $reg->mapModel(Model::create(Blocks::FROSTED_ICE(), Ids::FROSTED_ICE)->properties([
+ new IntProperty(StateNames::AGE, 0, 3, fn(FrostedIce $b) => $b->getAge(), fn(FrostedIce $b, int $v) => $b->setAge($v))
+ ]));
+
+ //G
+ $reg->mapModel(Model::create(Blocks::GLOWING_ITEM_FRAME(), Ids::GLOW_FRAME)->properties($commonProperties->itemFrameProperties));
+
+ //H
+ $reg->mapModel(Model::create(Blocks::HAY_BALE(), Ids::HAY_BLOCK)->properties([
+ IntProperty::unused(StateNames::DEPRECATED, 0),
+ $commonProperties->pillarAxis
+ ]));
+ $reg->mapModel(Model::create(Blocks::HOPPER(), Ids::HOPPER)->properties([
+ //kinda weird this doesn't use powered_bit?
+ new BoolProperty(StateNames::TOGGLE_BIT, fn(PoweredByRedstone $b) => $b->isPowered(), fn(PoweredByRedstone $b, bool $v) => $b->setPowered($v)),
+ new ValueFromIntProperty(StateNames::FACING_DIRECTION, ValueMappings::getInstance()->facingExceptUp, fn(Hopper $b) => $b->getFacing()->value, fn(Hopper $b, int $v) => $b->setFacing(Facing::from($v))),
+ ]));
+
+ //I
+ $reg->mapModel(Model::create(Blocks::IRON_DOOR(), Ids::IRON_DOOR)->properties($commonProperties->doorProperties));
+ $reg->mapModel(Model::create(Blocks::IRON_TRAPDOOR(), Ids::IRON_TRAPDOOR)->properties($commonProperties->trapdoorProperties));
+ $reg->mapModel(Model::create(Blocks::ITEM_FRAME(), Ids::FRAME)->properties($commonProperties->itemFrameProperties));
+
+ //L
+ $reg->mapModel(Model::create(Blocks::LADDER(), Ids::LADDER)->properties([$commonProperties->horizontalFacingClassic]));
+ $reg->mapModel(Model::create(Blocks::LANTERN(), Ids::LANTERN)->properties([
+ new BoolProperty(StateNames::HANGING, fn(Lantern $b) => $b->isHanging(), fn(Lantern $b, bool $v) => $b->setHanging($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::LECTERN(), Ids::LECTERN)->properties([
+ new BoolProperty(StateNames::POWERED_BIT, fn(Lectern $b) => $b->isProducingSignal(), fn(Lectern $b, bool $v) => $b->setProducingSignal($v)),
+ $commonProperties->horizontalFacingCardinal,
+ ]));
+ $reg->mapModel(Model::create(Blocks::LEVER(), Ids::LEVER)->properties([
+ new ValueFromStringProperty(StateNames::LEVER_DIRECTION, ValueMappings::getInstance()->leverFacing, fn(Lever $b) => $b->getFacing(), fn(Lever $b, LeverFacing $v) => $b->setFacing($v)),
+ new BoolProperty(StateNames::OPEN_BIT, fn(Lever $b) => $b->isActivated(), fn(Lever $b, bool $v) => $b->setActivated($v)),
+ ]));
+ $reg->mapModel(Model::create(Blocks::LIGHTNING_ROD(), Ids::LIGHTNING_ROD)->properties([$commonProperties->anyFacingClassic]));
+ $reg->mapModel(Model::create(Blocks::LIT_PUMPKIN(), Ids::LIT_PUMPKIN)->properties([$commonProperties->horizontalFacingCardinal]));
+ $reg->mapModel(Model::create(Blocks::LOOM(), Ids::LOOM)->properties([$commonProperties->horizontalFacingSWNE]));
+
+ //M
+ $reg->mapModel(Model::create(Blocks::MUDDY_MANGROVE_ROOTS(), Ids::MUDDY_MANGROVE_ROOTS)->properties([$commonProperties->pillarAxis]));
+ $reg->mapModel(Model::create(Blocks::NETHER_WART(), Ids::NETHER_WART)->properties([
+ new IntProperty(StateNames::AGE, 0, 3, fn(NetherWartPlant $b) => $b->getAge(), fn(NetherWartPlant $b, int $v) => $b->setAge($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::NETHER_PORTAL(), Ids::PORTAL)->properties([
+ //TODO: hack for lack of horizontal axis enum :(
+ new ValueFromStringProperty(StateNames::PORTAL_AXIS, ValueMappings::getInstance()->portalAxis, fn(NetherPortal $b) => $b->getAxis()->value, fn(NetherPortal $b, int $v) => $b->setAxis(Axis::from($v)))
+ ]));
+
+ //P
+ $reg->mapModel(Model::create(Blocks::PINK_PETALS(), Ids::PINK_PETALS)->properties([
+ //Pink petals only uses 0-3, but GROWTH state can go up to 7
+ new IntProperty(StateNames::GROWTH, 0, 7, fn(PinkPetals $b) => $b->getCount(), fn(PinkPetals $b, int $v) => $b->setCount(min($v, PinkPetals::MAX_COUNT)), offset: 1),
+ $commonProperties->horizontalFacingCardinal
+ ]));
+ $reg->mapModel(Model::create(Blocks::POWERED_RAIL(), Ids::GOLDEN_RAIL)->properties([
+ new BoolProperty(StateNames::RAIL_DATA_BIT, fn(PoweredRail $b) => $b->isPowered(), fn(PoweredRail $b, bool $v) => $b->setPowered($v)), //TODO: shared with ActivatorRail
+ $commonProperties->straightOnlyRailShape
+ ]));
+ $reg->mapModel(Model::create(Blocks::PITCHER_PLANT(), Ids::PITCHER_PLANT)->properties([
+ new BoolProperty(StateNames::UPPER_BLOCK_BIT, fn(DoublePlant $b) => $b->isTop(), fn(DoublePlant $b, bool $v) => $b->setTop($v)), //TODO: don't we have helpers for this?
+ ]));
+ $reg->mapModel(Model::create(Blocks::POLISHED_BASALT(), Ids::POLISHED_BASALT)->properties([$commonProperties->pillarAxis]));
+ $reg->mapModel(Model::create(Blocks::POLISHED_BLACKSTONE_BUTTON(), Ids::POLISHED_BLACKSTONE_BUTTON)->properties($commonProperties->buttonProperties));
+ $reg->mapModel(Model::create(Blocks::POLISHED_BLACKSTONE_PRESSURE_PLATE(), Ids::POLISHED_BLACKSTONE_PRESSURE_PLATE)->properties($commonProperties->simplePressurePlateProperties));
+ $reg->mapModel(Model::create(Blocks::PUMPKIN(), Ids::PUMPKIN)->properties([
+ //not used, has no visible effect
+ $commonProperties->dummyCardinalDirection
+ ]));
+ $reg->mapModel(Model::create(Blocks::PURPUR(), Ids::PURPUR_BLOCK)->properties([
+ $commonProperties->dummyPillarAxis
+ ]));
+ $reg->mapModel(Model::create(Blocks::PURPUR_PILLAR(), Ids::PURPUR_PILLAR)->properties([$commonProperties->pillarAxis]));
+
+ //Q
+ $reg->mapModel(Model::create(Blocks::QUARTZ(), Ids::QUARTZ_BLOCK)->properties([
+ $commonProperties->dummyPillarAxis
+ ]));
+ $reg->mapModel(Model::create(Blocks::QUARTZ_PILLAR(), Ids::QUARTZ_PILLAR)->properties([$commonProperties->pillarAxis]));
+
+ //R
+ $reg->mapModel(Model::create(Blocks::RAIL(), Ids::RAIL)->properties([
+ new ValueFromIntProperty(StateNames::RAIL_DIRECTION, EnumFromRawStateMap::int(RailShape::class, fn(RailShape $case) => match($case){
+ RailShape::FLAT_AXIS_Z => BlockLegacyMetadata::RAIL_STRAIGHT_NORTH_SOUTH,
+ RailShape::FLAT_AXIS_X => BlockLegacyMetadata::RAIL_STRAIGHT_EAST_WEST,
+ RailShape::ASCENDING_EAST => BlockLegacyMetadata::RAIL_ASCENDING_EAST,
+ RailShape::ASCENDING_WEST => BlockLegacyMetadata::RAIL_ASCENDING_WEST,
+ RailShape::ASCENDING_NORTH => BlockLegacyMetadata::RAIL_ASCENDING_NORTH,
+ RailShape::ASCENDING_SOUTH => BlockLegacyMetadata::RAIL_ASCENDING_SOUTH,
+ RailShape::CURVED_NORTHEAST => BlockLegacyMetadata::RAIL_CURVE_NORTHEAST,
+ RailShape::CURVED_NORTHWEST => BlockLegacyMetadata::RAIL_CURVE_NORTHWEST,
+ RailShape::CURVED_SOUTHEAST => BlockLegacyMetadata::RAIL_CURVE_SOUTHEAST,
+ RailShape::CURVED_SOUTHWEST => BlockLegacyMetadata::RAIL_CURVE_SOUTHWEST,
+ }), fn(Rail $b) => $b->getShape(), fn(Rail $b, RailShape $v) => $b->setShape($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::REDSTONE_WIRE(), Ids::REDSTONE_WIRE)->properties([$commonProperties->analogRedstoneSignal]));
+ $reg->mapModel(Model::create(Blocks::RESPAWN_ANCHOR(), Ids::RESPAWN_ANCHOR)->properties([
+ new IntProperty(StateNames::RESPAWN_ANCHOR_CHARGE, 0, 4, fn(RespawnAnchor $b) => $b->getCharges(), fn(RespawnAnchor $b, int $v) => $b->setCharges($v))
+ ]));
+
+ //S
+ $reg->mapModel(Model::create(Blocks::SEA_PICKLE(), Ids::SEA_PICKLE)->properties([
+ new IntProperty(StateNames::CLUSTER_COUNT, 0, 3, fn(SeaPickle $b) => $b->getCount(), fn(SeaPickle $b, int $v) => $b->setCount($v), offset: 1),
+ new BoolProperty(StateNames::DEAD_BIT, fn(SeaPickle $b) => $b->isUnderwater(), fn(SeaPickle $b, bool $v) => $b->setUnderwater($v), inverted: true)
+ ]));
+ $reg->mapModel(Model::create(Blocks::SMALL_DRIPLEAF(), Ids::SMALL_DRIPLEAF_BLOCK)->properties([
+ new BoolProperty(StateNames::UPPER_BLOCK_BIT, fn(SmallDripleaf $b) => $b->isTop(), fn(SmallDripleaf $b, bool $v) => $b->setTop($v)),
+ $commonProperties->horizontalFacingCardinal
+ ]));
+ $reg->mapModel(Model::create(Blocks::SMOOTH_QUARTZ(), Ids::SMOOTH_QUARTZ)->properties([
+ $commonProperties->dummyPillarAxis
+ ]));
+ $reg->mapModel(Model::create(Blocks::SNOW_LAYER(), Ids::SNOW_LAYER)->properties([
+ new DummyProperty(StateNames::COVERED_BIT, false),
+ new IntProperty(StateNames::HEIGHT, 0, 7, fn(SnowLayer $b) => $b->getLayers(), fn(SnowLayer $b, int $v) => $b->setLayers($v), offset: 1)
+ ]));
+ $reg->mapModel(Model::create(Blocks::SOUL_CAMPFIRE(), Ids::SOUL_CAMPFIRE)->properties($commonProperties->campfireProperties));
+ $reg->mapModel(Model::create(Blocks::SOUL_FIRE(), Ids::SOUL_FIRE)->properties([
+ new DummyProperty(StateNames::AGE, 0) //this is useless for soul fire, since it doesn't have the logic associated
+ ]));
+ $reg->mapModel(Model::create(Blocks::SOUL_LANTERN(), Ids::SOUL_LANTERN)->properties([
+ new BoolProperty(StateNames::HANGING, fn(Lantern $b) => $b->isHanging(), fn(Lantern $b, bool $v) => $b->setHanging($v)) //TODO: repeated
+ ]));
+ $reg->mapModel(Model::create(Blocks::STONE_BUTTON(), Ids::STONE_BUTTON)->properties($commonProperties->buttonProperties));
+ $reg->mapModel(Model::create(Blocks::STONE_PRESSURE_PLATE(), Ids::STONE_PRESSURE_PLATE)->properties($commonProperties->simplePressurePlateProperties));
+ $reg->mapModel(Model::create(Blocks::STONECUTTER(), Ids::STONECUTTER_BLOCK)->properties([
+ $commonProperties->horizontalFacingCardinal
+ ]));
+ $reg->mapModel(Model::create(Blocks::SUGARCANE(), Ids::REEDS)->properties([
+ new IntProperty(StateNames::AGE, 0, 15, fn(Sugarcane $b) => $b->getAge(), fn(Sugarcane $b, int $v) => $b->setAge($v))
+ ]));
+
+ //T
+ $reg->mapModel(Model::create(Blocks::TRAPPED_CHEST(), Ids::TRAPPED_CHEST)->properties([
+ $commonProperties->horizontalFacingCardinal
+ ]));
+ $reg->mapModel(Model::create(Blocks::TRIPWIRE(), Ids::TRIP_WIRE)->properties([
+ new BoolProperty(StateNames::ATTACHED_BIT, fn(Tripwire $b) => $b->isConnected(), fn(Tripwire $b, bool $v) => $b->setConnected($v)),
+ new BoolProperty(StateNames::DISARMED_BIT, fn(Tripwire $b) => $b->isDisarmed(), fn(Tripwire $b, bool $v) => $b->setDisarmed($v)),
+ new BoolProperty(StateNames::SUSPENDED_BIT, fn(Tripwire $b) => $b->isSuspended(), fn(Tripwire $b, bool $v) => $b->setSuspended($v)),
+ new BoolProperty(StateNames::POWERED_BIT, fn(Tripwire $b) => $b->isTriggered(), fn(Tripwire $b, bool $v) => $b->setTriggered($v)),
+ ]));
+ $reg->mapModel(Model::create(Blocks::TRIPWIRE_HOOK(), Ids::TRIPWIRE_HOOK)->properties([
+ new BoolProperty(StateNames::ATTACHED_BIT, fn(TripwireHook $b) => $b->isConnected(), fn(TripwireHook $b, bool $v) => $b->setConnected($v)),
+ new BoolProperty(StateNames::POWERED_BIT, fn(TripwireHook $b) => $b->isPowered(), fn(TripwireHook $b, bool $v) => $b->setPowered($v)),
+ $commonProperties->horizontalFacingSWNE
+ ]));
+
+ $reg->mapModel(Model::create(Blocks::TWISTING_VINES(), Ids::TWISTING_VINES)->properties([
+ new IntProperty(StateNames::TWISTING_VINES_AGE, 0, 25, fn(NetherVines $b) => $b->getAge(), fn(NetherVines $b, int $v) => $b->setAge($v))
+ ]));
+
+ //W
+ $reg->mapModel(Model::create(Blocks::WALL_BANNER(), Ids::WALL_BANNER)->properties([$commonProperties->horizontalFacingClassic]));
+ $reg->mapModel(Model::create(Blocks::WEEPING_VINES(), Ids::WEEPING_VINES)->properties([
+ new IntProperty(StateNames::WEEPING_VINES_AGE, 0, 25, fn(NetherVines $b) => $b->getAge(), fn(NetherVines $b, int $v) => $b->setAge($v))
+ ]));
+ $reg->mapModel(Model::create(Blocks::WEIGHTED_PRESSURE_PLATE_HEAVY(), Ids::HEAVY_WEIGHTED_PRESSURE_PLATE)->properties([$commonProperties->analogRedstoneSignal]));
+ $reg->mapModel(Model::create(Blocks::WEIGHTED_PRESSURE_PLATE_LIGHT(), Ids::LIGHT_WEIGHTED_PRESSURE_PLATE)->properties([$commonProperties->analogRedstoneSignal]));
+ }
+
+ /**
+ * @phpstan-template TBlock of Block
+ * @phpstan-param Model $model
+ */
+ private static function mapAsymmetricSerializer(BlockSerializerDeserializerRegistrar $reg, Model $model) : void{
+ $id = $model->getId();
+ $properties = $model->getProperties();
+ $reg->serializer->map($model->getBlock(), function(Block $block) use ($id, $properties) : Writer{
+ $writer = new Writer($id);
+ foreach($properties as $property){
+ $property->serialize($block, $writer);
+ }
+ return $writer;
+ });
+ }
+
+ /**
+ * @phpstan-template TBlock of Block
+ * @phpstan-param Model $model
+ * @phpstan-return TBlock
+ */
+ private static function deserializeAsymmetric(Model $model, Reader $in) : Block{
+ $block = clone $model->getBlock();
+ foreach($model->getProperties() as $property){
+ $property->deserialize($block, $in);
+ }
+ return $block;
+ }
+
+ /**
+ * All mappings that still use the split form of serializer/deserializer registration
+ * This is typically only used by blocks with one ID but multiple PM types (split by property)
+ * These currently can't be registered in a unified way, and due to their small number it may not be worth the
+ * effort to implement a unified way to deal with them
+ */
+ private static function registerSplitMappings(BlockSerializerDeserializerRegistrar $reg, CommonProperties $commonProperties) : void{
+ //big dripleaf - split into head / stem variants, as stems don't have tilt or leaf state
+ $bigDripleafHeadModel = Model::create(Blocks::BIG_DRIPLEAF_HEAD(), Ids::BIG_DRIPLEAF)->properties([
+ $commonProperties->horizontalFacingCardinal,
+ new ValueFromStringProperty(StateNames::BIG_DRIPLEAF_TILT, ValueMappings::getInstance()->dripleafState, fn(BigDripleafHead $b) => $b->getLeafState(), fn(BigDripleafHead $b, DripleafState $v) => $b->setLeafState($v)),
+ new DummyProperty(StateNames::BIG_DRIPLEAF_HEAD, true)
+ ]);
+ $bigDripleafStemModel = Model::create(Blocks::BIG_DRIPLEAF_STEM(), Ids::BIG_DRIPLEAF)->properties([
+ $commonProperties->horizontalFacingCardinal,
+ new DummyProperty(StateNames::BIG_DRIPLEAF_TILT, StringValues::BIG_DRIPLEAF_TILT_NONE),
+ new DummyProperty(StateNames::BIG_DRIPLEAF_HEAD, false)
+ ]);
+ self::mapAsymmetricSerializer($reg, $bigDripleafHeadModel);
+ self::mapAsymmetricSerializer($reg, $bigDripleafStemModel);
+ $reg->deserializer->map(Ids::BIG_DRIPLEAF, fn(Reader $in) => $in->readBool(StateNames::BIG_DRIPLEAF_HEAD) ?
+ self::deserializeAsymmetric($bigDripleafHeadModel, $in) :
+ self::deserializeAsymmetric($bigDripleafStemModel, $in)
+ );
+
+ $fillLevelProperty = new IntProperty(StateNames::FILL_LEVEL, 1, 6, fn(FillableCauldron $b) => $b->getFillLevel(), fn(FillableCauldron $b, int $v) => $b->setFillLevel($v));
+
+ //this pretends to be a water cauldron on disk and stores its real information in the block actor data, therefore only a serializer is needed
+ self::mapAsymmetricSerializer($reg, Model::create(Blocks::POTION_CAULDRON(), Ids::CAULDRON)->properties([$fillLevelProperty, new DummyProperty(StateNames::CAULDRON_LIQUID, StringValues::CAULDRON_LIQUID_WATER)]));
+
+ $lavaCauldronModel = Model::create(Blocks::LAVA_CAULDRON(), Ids::CAULDRON)->properties([
+ $fillLevelProperty,
+ new DummyProperty(StateNames::CAULDRON_LIQUID, StringValues::CAULDRON_LIQUID_LAVA)
+ ]);
+ $waterCauldronModel = Model::create(Blocks::WATER_CAULDRON(), Ids::CAULDRON)->properties([
+ $fillLevelProperty,
+ new DummyProperty(StateNames::CAULDRON_LIQUID, StringValues::CAULDRON_LIQUID_WATER)
+ ]);
+ $emptyCauldronModel = Model::create(Blocks::CAULDRON(), Ids::CAULDRON)->properties([
+ new DummyProperty(StateNames::FILL_LEVEL, 0),
+ new DummyProperty(StateNames::CAULDRON_LIQUID, StringValues::CAULDRON_LIQUID_WATER)
+ ]);
+ self::mapAsymmetricSerializer($reg, $lavaCauldronModel);
+ self::mapAsymmetricSerializer($reg, $waterCauldronModel);
+ self::mapAsymmetricSerializer($reg, $emptyCauldronModel);
+ $reg->deserializer->map(Ids::CAULDRON, fn(Reader $in) => $in->readInt(StateNames::FILL_LEVEL) === 0 ?
+ self::deserializeAsymmetric($emptyCauldronModel, $in) :
+ match ($liquid = $in->readString(StateNames::CAULDRON_LIQUID)) {
+ StringValues::CAULDRON_LIQUID_WATER => self::deserializeAsymmetric($waterCauldronModel, $in),
+ StringValues::CAULDRON_LIQUID_LAVA => self::deserializeAsymmetric($lavaCauldronModel, $in),
+ StringValues::CAULDRON_LIQUID_POWDER_SNOW => throw new UnsupportedBlockStateException("Powder snow is not supported yet"),
+ default => throw $in->badValueException(StateNames::CAULDRON_LIQUID, $liquid)
+ }
+ );
+
+ //mushroom stems, split for consistency with all-sided logs vs normal logs
+ $allSidedMushroomStemModel = Model::create(Blocks::ALL_SIDED_MUSHROOM_STEM(), Ids::MUSHROOM_STEM)->properties([new DummyProperty(StateNames::HUGE_MUSHROOM_BITS, BlockLegacyMetadata::MUSHROOM_BLOCK_ALL_STEM)]);
+ $mushroomStemModel = Model::create(Blocks::MUSHROOM_STEM(), Ids::MUSHROOM_STEM)->properties([new DummyProperty(StateNames::HUGE_MUSHROOM_BITS, BlockLegacyMetadata::MUSHROOM_BLOCK_STEM)]);
+ self::mapAsymmetricSerializer($reg, $allSidedMushroomStemModel);
+ self::mapAsymmetricSerializer($reg, $mushroomStemModel);
+ $reg->deserializer->map(Ids::MUSHROOM_STEM, fn(Reader $in) : Block => match ($in->readInt(StateNames::HUGE_MUSHROOM_BITS)) {
+ BlockLegacyMetadata::MUSHROOM_BLOCK_ALL_STEM => self::deserializeAsymmetric($allSidedMushroomStemModel, $in),
+ BlockLegacyMetadata::MUSHROOM_BLOCK_STEM => self::deserializeAsymmetric($mushroomStemModel, $in),
+ default => throw new BlockStateDeserializeException("This state does not exist"),
+ });
+
+ //pitcher crop, split into single and double variants as double has different properties and behaviour
+ //this will probably be the most annoying to unify
+ $pitcherCropModel = Model::create(Blocks::PITCHER_CROP(), Ids::PITCHER_CROP)->properties([
+ new IntProperty(StateNames::GROWTH, 0, PitcherCrop::MAX_AGE, fn(PitcherCrop $b) => $b->getAge(), fn(PitcherCrop $b, int $v) => $b->setAge($v)),
+ new DummyProperty(StateNames::UPPER_BLOCK_BIT, false)
+ ]);
+ $doublePitcherCropAgeOffset = PitcherCrop::MAX_AGE + 1;
+ $doublePitcherCropModel = Model::create(Blocks::DOUBLE_PITCHER_CROP(), Ids::PITCHER_CROP)->properties([
+ new IntProperty(
+ StateNames::GROWTH,
+ $doublePitcherCropAgeOffset, //TODO: it would be a bit less awkward if the bounds applied _after_ applying the offset, instead of before
+ 7,
+ fn(DoublePitcherCrop $b) => $b->getAge(),
+ fn(DoublePitcherCrop $b, int $v) => $b->setAge(min($v, DoublePitcherCrop::MAX_AGE)), //state may give up to 7, but only up to 4 is valid
+ offset: -$doublePitcherCropAgeOffset
+ ),
+ new BoolProperty(StateNames::UPPER_BLOCK_BIT, fn(DoublePitcherCrop $b) => $b->isTop(), fn(DoublePitcherCrop $b, bool $v) => $b->setTop($v))
+ ]);
+ self::mapAsymmetricSerializer($reg, $pitcherCropModel);
+ self::mapAsymmetricSerializer($reg, $doublePitcherCropModel);
+ $reg->deserializer->map(Ids::PITCHER_CROP, fn(Reader $in) => $in->readInt(StateNames::GROWTH) <= PitcherCrop::MAX_AGE ?
+ ($in->readBool(StateNames::UPPER_BLOCK_BIT) ?
+ //top pitcher crop with age 0-2 is an invalid state, only the bottom half should exist in this case
+ Blocks::AIR() :
+ self::deserializeAsymmetric($pitcherCropModel, $in)
+ ) : self::deserializeAsymmetric($doublePitcherCropModel, $in)
+ );
+
+ //these only exist within PM (mapped from tile properties) as they don't support the same properties as a
+ //normal banner, therefore no deserializer is needed
+ self::mapAsymmetricSerializer($reg, Model::create(Blocks::OMINOUS_BANNER(), Ids::STANDING_BANNER)->properties([$commonProperties->floorSignLikeRotation]));
+ self::mapAsymmetricSerializer($reg, Model::create(Blocks::OMINOUS_WALL_BANNER(), Ids::WALL_BANNER)->properties([$commonProperties->horizontalFacingClassic]));
+
+ foreach([
+ Ids::ACACIA_HANGING_SIGN => [Blocks::ACACIA_CEILING_CENTER_HANGING_SIGN(), Blocks::ACACIA_CEILING_EDGES_HANGING_SIGN(), Blocks::ACACIA_WALL_HANGING_SIGN()],
+ Ids::BIRCH_HANGING_SIGN => [Blocks::BIRCH_CEILING_CENTER_HANGING_SIGN(), Blocks::BIRCH_CEILING_EDGES_HANGING_SIGN(), Blocks::BIRCH_WALL_HANGING_SIGN()],
+ Ids::CHERRY_HANGING_SIGN => [Blocks::CHERRY_CEILING_CENTER_HANGING_SIGN(), Blocks::CHERRY_CEILING_EDGES_HANGING_SIGN(), Blocks::CHERRY_WALL_HANGING_SIGN()],
+ Ids::CRIMSON_HANGING_SIGN => [Blocks::CRIMSON_CEILING_CENTER_HANGING_SIGN(), Blocks::CRIMSON_CEILING_EDGES_HANGING_SIGN(), Blocks::CRIMSON_WALL_HANGING_SIGN()],
+ Ids::DARK_OAK_HANGING_SIGN => [Blocks::DARK_OAK_CEILING_CENTER_HANGING_SIGN(), Blocks::DARK_OAK_CEILING_EDGES_HANGING_SIGN(), Blocks::DARK_OAK_WALL_HANGING_SIGN()],
+ Ids::JUNGLE_HANGING_SIGN => [Blocks::JUNGLE_CEILING_CENTER_HANGING_SIGN(), Blocks::JUNGLE_CEILING_EDGES_HANGING_SIGN(), Blocks::JUNGLE_WALL_HANGING_SIGN()],
+ Ids::MANGROVE_HANGING_SIGN => [Blocks::MANGROVE_CEILING_CENTER_HANGING_SIGN(), Blocks::MANGROVE_CEILING_EDGES_HANGING_SIGN(), Blocks::MANGROVE_WALL_HANGING_SIGN()],
+ Ids::OAK_HANGING_SIGN => [Blocks::OAK_CEILING_CENTER_HANGING_SIGN(), Blocks::OAK_CEILING_EDGES_HANGING_SIGN(), Blocks::OAK_WALL_HANGING_SIGN()],
+ Ids::PALE_OAK_HANGING_SIGN => [Blocks::PALE_OAK_CEILING_CENTER_HANGING_SIGN(), Blocks::PALE_OAK_CEILING_EDGES_HANGING_SIGN(), Blocks::PALE_OAK_WALL_HANGING_SIGN()],
+ Ids::SPRUCE_HANGING_SIGN => [Blocks::SPRUCE_CEILING_CENTER_HANGING_SIGN(), Blocks::SPRUCE_CEILING_EDGES_HANGING_SIGN(), Blocks::SPRUCE_WALL_HANGING_SIGN()],
+ Ids::WARPED_HANGING_SIGN => [Blocks::WARPED_CEILING_CENTER_HANGING_SIGN(), Blocks::WARPED_CEILING_EDGES_HANGING_SIGN(), Blocks::WARPED_WALL_HANGING_SIGN()],
+ ] as $id => [$center, $edges, $wall]){
+ //attached_bit - true for ceiling center signs, false for ceiling edges signs and wall signs
+ //hanging - true for all ceiling signs, false for wall signs
+ //facing_direction - used for ceiling edges signs and wall signs
+ //ground_sign_direction - used by ceiling center signs only
+ $centerModel = Model::create($center, $id)->properties([
+ $commonProperties->floorSignLikeRotation,
+ new DummyProperty(StateNames::ATTACHED_BIT, true),
+ new DummyProperty(StateNames::HANGING, true),
+ new DummyProperty(StateNames::FACING_DIRECTION, 2)
+ ]);
+ $edgesModel = Model::create($edges, $id)->properties([
+ new DummyProperty(StateNames::GROUND_SIGN_DIRECTION, 0),
+ new DummyProperty(StateNames::ATTACHED_BIT, false),
+ new DummyProperty(StateNames::HANGING, true),
+ $commonProperties->horizontalFacingClassic,
+ ]);
+ $wallModel = Model::create($wall, $id)->properties([
+ new DummyProperty(StateNames::GROUND_SIGN_DIRECTION, 0),
+ new DummyProperty(StateNames::ATTACHED_BIT, false),
+ new DummyProperty(StateNames::HANGING, false),
+ $commonProperties->horizontalFacingClassic
+ ]);
+ self::mapAsymmetricSerializer($reg, $centerModel);
+ self::mapAsymmetricSerializer($reg, $edgesModel);
+ self::mapAsymmetricSerializer($reg, $wallModel);
+ $reg->deserializer->map($id, fn(Reader $in) => $in->readBool(StateNames::HANGING) ?
+ ($in->readBool(StateNames::ATTACHED_BIT) ?
+ self::deserializeAsymmetric($centerModel, $in) :
+ self::deserializeAsymmetric($edgesModel, $in)
+ ) :
+ self::deserializeAsymmetric($wallModel, $in));
+ }
+ }
+}
diff --git a/src/data/bedrock/block/convert/property/BoolFromStringProperty.php b/src/data/bedrock/block/convert/property/BoolFromStringProperty.php
new file mode 100644
index 000000000..89c64188d
--- /dev/null
+++ b/src/data/bedrock/block/convert/property/BoolFromStringProperty.php
@@ -0,0 +1,78 @@
+
+ */
+final class BoolFromStringProperty implements StringProperty{
+
+ /**
+ * @param \Closure(TBlock) : bool $getter
+ * @param \Closure(TBlock, bool) : mixed $setter
+ */
+ public function __construct(
+ private string $name,
+ private string $falseValue,
+ private string $trueValue,
+ private \Closure $getter,
+ private \Closure $setter
+ ){}
+
+ public function getName() : string{
+ return $this->name;
+ }
+
+ public function getPossibleValues() : array{
+ return [$this->falseValue, $this->trueValue];
+ }
+
+ public function deserialize(object $block, BlockStateReader $in) : void{
+ $this->deserializePlain($block, $in->readString($this->name));
+ }
+
+ public function deserializePlain(object $block, string $raw) : void{
+ $value = match($raw){
+ $this->falseValue => false,
+ $this->trueValue => true,
+ default => throw new BlockStateSerializeException("Invalid value for {$this->name}: $raw"),
+ };
+
+ ($this->setter)($block, $value);
+ }
+
+ public function serialize(object $block, BlockStateWriter $out) : void{
+ $out->writeString($this->name, $this->serializePlain($block));
+ }
+
+ public function serializePlain(object $block) : string{
+ $value = ($this->getter)($block);
+ return $value ? $this->trueValue : $this->falseValue;
+ }
+}
diff --git a/src/data/bedrock/block/convert/property/BoolProperty.php b/src/data/bedrock/block/convert/property/BoolProperty.php
new file mode 100644
index 000000000..299ec4076
--- /dev/null
+++ b/src/data/bedrock/block/convert/property/BoolProperty.php
@@ -0,0 +1,71 @@
+
+ */
+final class BoolProperty implements Property{
+ /**
+ * @phpstan-param \Closure(TBlock) : bool $getter
+ * @phpstan-param \Closure(TBlock, bool) : mixed $setter
+ */
+ public function __construct(
+ private string $name,
+ private \Closure $getter,
+ private \Closure $setter,
+ private bool $inverted = false //we don't *need* this, but it avoids accidentally forgetting a ! in the getter/setter closures (and makes it analysable)
+ ){}
+
+ /**
+ * @phpstan-return self