diff --git a/.github/workflows/build-remote.yml b/.github/workflows/build-remote.yml
index d49920785..7cb89cc61 100644
--- a/.github/workflows/build-remote.yml
+++ b/.github/workflows/build-remote.yml
@@ -22,81 +22,26 @@ jobs:
run: |
echo "BUILD_NUMBER=${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
- - name: Set up JDK 21
- # See https://github.com/actions/setup-java/commits
- uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
+ - name: Setup Gradle
+ uses: GeyserMC/actions/setup-gradle-composite@master
with:
- java-version: 21
- distribution: temurin
-
- - name: Checkout repository and submodules
- # See https://github.com/actions/checkout/commits
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- with:
- repository: ${{ inputs.repository }}
- ref: ${{ inputs.ref }}
- submodules: recursive
- path: geyser
-
- - name: Validate Gradle Wrapper
- # See https://github.com/gradle/wrapper-validation-action/commits
- uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1
+ checkout_repository: ${{ inputs.repository }}
+ checkout_ref: ${{ inputs.ref }}
+ setup-java_java-version: 21
+ setup-gradle_cache-read-only: true
- name: Build Geyser
- # See https://github.com/gradle/actions/commits
- uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
- with:
- arguments: build
- build-root-directory: geyser
- cache-read-only: true
+ run: ./gradlew build
- - name: Archive artifacts (Geyser Fabric)
- # See https://github.com/actions/upload-artifact/commits
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ - name: Archive Artifacts
+ uses: GeyserMC/actions/upload-multi-artifact@master
if: success()
with:
- name: Geyser Fabric
- path: geyser/bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser NeoForge)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser NeoForge
- path: geyser/bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser Standalone)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser Standalone
- path: geyser/bootstrap/standalone/build/libs/Geyser-Standalone.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser Spigot)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser Spigot
- path: geyser/bootstrap/spigot/build/libs/Geyser-Spigot.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser BungeeCord)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser BungeeCord
- path: geyser/bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser Velocity)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser Velocity
- path: geyser/bootstrap/velocity/build/libs/Geyser-Velocity.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser ViaProxy)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser ViaProxy
- path: geyser/bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar
- if-no-files-found: error
\ No newline at end of file
+ artifacts: |
+ bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar
+ bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar
+ bootstrap/standalone/build/libs/Geyser-Standalone.jar
+ bootstrap/spigot/build/libs/Geyser-Spigot.jar
+ bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar
+ bootstrap/velocity/build/libs/Geyser-Velocity.jar
+ bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar
\ No newline at end of file
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 7ec013dc2..0e94ce965 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -21,103 +21,55 @@ on:
jobs:
build:
runs-on: ubuntu-latest
- env:
- PROJECT: 'geyser'
steps:
- - name: Set Build Number
+ - name: Get Release Info
+ id: release-info
+ uses: GeyserMC/actions/previous-release@master
+ with:
+ data: ${{ vars.RELEASEACTION_PREVRELEASE }}
+
+ - name: Setup Gradle
+ uses: GeyserMC/actions/setup-gradle-composite@master
+ with:
+ setup-java_java-version: 21
+
+ - name: Build Geyser
+ run: ./gradlew build
env:
- BUILD_JSON: ${{ vars.RELEASEACTION_PREVRELEASE }}
- run: |
- BUILD_NUMBER=$(echo $BUILD_JSON | jq --arg branch "${GITHUB_REF_NAME}" 'if .[$branch] == null then 1 else .[$branch] | .t | tonumber + 1 end // 1')
- echo "BUILD_NUMBER=${BUILD_NUMBER:=$GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
-
- - name: Checkout repository and submodules
- # See https://github.com/actions/checkout/commits
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- with:
- submodules: recursive
-
- - name: Validate Gradle Wrapper
- # See https://github.com/gradle/wrapper-validation-action/commits
- uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1
-
- # See https://github.com/actions/setup-java/commits
- - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
- with:
- java-version: 21
- distribution: temurin
+ BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }}
- - name: Build
- # See https://github.com/gradle/actions/commits
- uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0
- with:
- arguments: build
- gradle-home-cache-cleanup: true
-
- - name: Archive artifacts (Geyser Fabric)
- # See https://github.com/actions/upload-artifact/commits
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ - name: Archive Artifacts
+ uses: GeyserMC/actions/upload-multi-artifact@master
if: success()
with:
- name: Geyser Fabric
- path: bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser NeoForge)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser NeoForge
- path: bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser Standalone)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser Standalone
- path: bootstrap/standalone/build/libs/Geyser-Standalone.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser Spigot)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser Spigot
- path: bootstrap/spigot/build/libs/Geyser-Spigot.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser BungeeCord)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser BungeeCord
- path: bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser Velocity)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser Velocity
- path: bootstrap/velocity/build/libs/Geyser-Velocity.jar
- if-no-files-found: error
- - name: Archive artifacts (Geyser ViaProxy)
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
- if: success()
- with:
- name: Geyser ViaProxy
- path: bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar
- if-no-files-found: error
+ artifacts: |
+ bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar
+ bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar
+ bootstrap/standalone/build/libs/Geyser-Standalone.jar
+ bootstrap/spigot/build/libs/Geyser-Spigot.jar
+ bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar
+ bootstrap/velocity/build/libs/Geyser-Velocity.jar
+ bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar
- name: Publish to Maven Repository
if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }}
- uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
+ run: ./gradlew publish
env:
+ BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }}
ORG_GRADLE_PROJECT_geysermcUsername: ${{ vars.DEPLOY_USER }}
ORG_GRADLE_PROJECT_geysermcPassword: ${{ secrets.DEPLOY_PASS }}
- with:
- arguments: publish
+
+ - name: Get Version
+ if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }}
+ id: get-version
+ run: |
+ version=$(cat gradle.properties | grep -o "version=[0-9\\.]*" | cut -d"=" -f2)
+ echo "VERSION=${version}" >> $GITHUB_OUTPUT
- name: Get Release Metadata
- if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }}
- # See https://github.com/Kas-tle/base-release-action/releases/tag/main-11
- uses: Kas-tle/base-release-action@b863fa0f89bd15267a96a72efb84aec25f168d4c # main-11
+ if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }}
+ uses: GeyserMC/actions/release@master
+ id: metadata
with:
appID: ${{ secrets.RELEASE_APP_ID }}
appPrivateKey: ${{ secrets.RELEASE_APP_PK }}
@@ -131,61 +83,45 @@ jobs:
viaproxy:bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar
releaseEnabled: false
saveMetadata: true
- - name: Update Generated Metadata
- if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }}
- run: |
- cat metadata.json
- echo
- mv metadata.json metadata.json.tmp
- version=$(cat gradle.properties | grep -o "version=[0-9\\.]*" | cut -d"=" -f2)
- jq --arg project "${PROJECT}" --arg version "${version}" '
- .
- | .changes |= map({"commit", "summary", "message"})
- | .downloads |= map_values({"name", "sha256"})
- | {$project, "repo", $version, "number": .build, "changes", "downloads"}
- ' metadata.json.tmp > metadata.json
- cat metadata.json
+ releaseProject: 'geyser'
+ releaseVersion: ${{ steps.get-version.outputs.VERSION }}
+
- name: Publish to Downloads API
if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }}
- shell: bash
- env:
- DOWNLOADS_USERNAME: ${{ vars.DOWNLOADS_USERNAME }}
- DOWNLOADS_PRIVATE_KEY: ${{ secrets.DOWNLOADS_PRIVATE_KEY }}
- DOWNLOADS_SERVER_IP: ${{ secrets.DOWNLOADS_SERVER_IP }}
- run: |
- # Save the private key to a file
- echo "$DOWNLOADS_PRIVATE_KEY" > id_ecdsa
- chmod 600 id_ecdsa
- # Create the build folder
- ssh -o StrictHostKeyChecking=no -i id_ecdsa $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP mkdir -p "~/uploads/$PROJECT/$GITHUB_RUN_NUMBER/"
- # Copy over artifacts
- rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" bootstrap/**/build/libs/Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$GITHUB_RUN_NUMBER/
- rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" bootstrap/mod/**/build/libs/Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$GITHUB_RUN_NUMBER/
- # Run the build script
- rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$GITHUB_RUN_NUMBER/
+ uses: GeyserMC/actions/upload-release@master
+ with:
+ username: ${{ vars.DOWNLOADS_USERNAME }}
+ privateKey: ${{ secrets.DOWNLOADS_PRIVATE_KEY }}
+ host: ${{ secrets.DOWNLOADS_SERVER_IP }}
+ files: |
+ bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar
+ bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar
+ bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar
+ bootstrap/spigot/build/libs/Geyser-Spigot.jar
+ bootstrap/standalone/build/libs/Geyser-Standalone.jar
+ bootstrap/velocity/build/libs/Geyser-Velocity.jar
+ bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar
+ changelog: ${{ steps.metadata.outputs.body }}
- name: Publish to Modrinth (Fabric)
- uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }}
env:
+ BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }}
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
- with:
- arguments: fabric:modrinth
- gradle-home-cache-cleanup: true
+ run: ./gradlew fabric:modrinth
- name: Publish to Modrinth (NeoForge)
- uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }}
env:
+ BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }}
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
- with:
- arguments: neoforge:modrinth
- gradle-home-cache-cleanup: true
+ run: ./gradlew neoforge:modrinth
- name: Notify Discord
if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }}
- # See https://github.com/Tim203/actions-git-discord-webhook/commits
- uses: Tim203/actions-git-discord-webhook@70f38ded3aca51635ec978ab4e1a58cd4cd0c2ff
+ uses: GeyserMC/actions/notify-discord@master
with:
- webhook_url: ${{ secrets.DISCORD_WEBHOOK }}
+ discordWebhook: ${{ secrets.DISCORD_WEBHOOK }}
status: ${{ job.status }}
+ body: ${{ steps.metadata.outputs.body }}
+ includeDownloads: ${{ github.ref_name == 'master' }}
diff --git a/.github/workflows/dispatch-preview.yml b/.github/workflows/dispatch-preview.yml
new file mode 100644
index 000000000..83df08e37
--- /dev/null
+++ b/.github/workflows/dispatch-preview.yml
@@ -0,0 +1,33 @@
+name: Dispatch Preview
+
+on:
+ workflow_dispatch:
+ inputs:
+ runId:
+ required: true
+ description: 'ID of the action to pull artifacts from'
+ build:
+ required: true
+ description: 'Build number for the release'
+ version:
+ required: true
+ description: 'Version under which to upload to the Downloads API'
+
+jobs:
+ dispatch-preview:
+ # Allow access to secrets if we are uploading a preview
+ secrets: inherit
+ uses: GeyserMC/actions/.github/workflows/upload-preview.yml@master
+ with:
+ build: ${{ inputs.build }}
+ version: ${{ inputs.version }}
+ files: |
+ bungeecord:Geyser-BungeeCord.jar
+ fabric:Geyser-Fabric.jar
+ neoforge:Geyser-NeoForge.jar
+ spigot:Geyser-Spigot.jar
+ standalone:Geyser-Standalone.jar
+ velocity:Geyser-Velocity.jar
+ viaproxy:Geyser-ViaProxy.jar
+ project: geyserpreview
+ runId: ${{ inputs.runId }}
\ No newline at end of file
diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
deleted file mode 100644
index 1268f0674..000000000
--- a/.github/workflows/preview.yml
+++ /dev/null
@@ -1,96 +0,0 @@
-name: Upload Preview
-
-on:
- workflow_dispatch:
- inputs:
- runId:
- required: true
- description: 'ID of the action to pull artifacts from'
- build:
- required: true
- description: 'Build number for the release'
- version:
- required: true
- description: 'Version under which to upload to the Downloads API'
- workflow_call:
- inputs:
- build:
- required: true
- description: 'Build number for the release'
- type: string
- version:
- required: true
- description: 'Version under which to upload to the Downloads API'
- type: string
-
-jobs:
- upload:
- runs-on: ubuntu-latest
- env:
- PROJECT: 'geyserpreview'
- steps:
- - name: Set Variables
- id: setvars
- run: |
- if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
- echo "BUILD=${{ github.event.inputs.build }}" >> $GITHUB_ENV
- echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
- echo "RUN=${{ github.event.inputs.runId }}" >> $GITHUB_OUTPUT
- else
- echo "BUILD=${{ inputs.build }}" >> $GITHUB_ENV
- echo "VERSION=${{ inputs.version }}" >> $GITHUB_ENV
- echo "RUN=${{ github.run_id }}" >> $GITHUB_OUTPUT
- fi
- - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427
- with:
- run-id: ${{ steps.setvars.outputs.RUN }}
- github-token: ${{ secrets.GITHUB_TOKEN }}
- merge-multiple: true
- - name: Get Preview Metadata
- if: success()
- # See https://github.com/Kas-tle/base-release-action/releases/tag/main-11
- uses: Kas-tle/base-release-action@664c39985eb9d0d393ce98e7eb8414d3d98e762a # main-11
- with:
- appID: ${{ secrets.RELEASE_APP_ID }}
- appPrivateKey: ${{ secrets.RELEASE_APP_PK }}
- files: |
- bungeecord:Geyser-BungeeCord.jar
- fabric:Geyser-Fabric.jar
- neoforge:Geyser-NeoForge.jar
- spigot:Geyser-Spigot.jar
- standalone:Geyser-Standalone.jar
- velocity:Geyser-Velocity.jar
- viaproxy:Geyser-ViaProxy.jar
- releaseEnabled: false
- saveMetadata: true
- updateReleaseData: false
- - name: Update Generated Metadata
- if: success()
- run: |
- cat metadata.json
- echo
- mv metadata.json metadata.json.tmp
- jq --arg project "${PROJECT}" --arg version "${VERSION}" --arg number "${BUILD}" '
- .
- | .downloads |= map_values({"name", "sha256"})
- | {$project, "repo", $version, "number": $number | tonumber, "changes": [], "downloads"}
- ' metadata.json.tmp > metadata.json
- cat metadata.json
- - name: Publish to Downloads API
- if: success()
- shell: bash
- env:
- DOWNLOADS_USERNAME: ${{ vars.DOWNLOADS_USERNAME }}
- DOWNLOADS_PRIVATE_KEY: ${{ secrets.DOWNLOADS_PRIVATE_KEY }}
- DOWNLOADS_SERVER_IP: ${{ secrets.DOWNLOADS_SERVER_IP }}
- run: |
- # Save the private key to a file
- echo "$DOWNLOADS_PRIVATE_KEY" > id_ecdsa
- chmod 600 id_ecdsa
- # Create the build folder
- ssh -o StrictHostKeyChecking=no -i id_ecdsa $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP mkdir -p "~/uploads/$PROJECT/$BUILD/"
- # Copy over artifacts
- rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" Geyser-*.jar $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$BUILD/
- # Run the build script
- # Push the metadata
- rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$BUILD/
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index bc5e57b6b..6167bb18e 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -8,7 +8,7 @@ jobs:
# Forbid access to secrets nor GH Token perms while building the PR
permissions: {}
secrets: {}
- uses: ./.github/workflows/build-remote.yml
+ uses: GeyserMC/Geyser/.github/workflows/build-remote.yml@master
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}
@@ -18,7 +18,17 @@ jobs:
contains(github.event.pull_request.labels.*.name, 'PR: Needs Testing')
# Allow access to secrets if we are uploading a preview
secrets: inherit
- uses: ./.github/workflows/preview.yml
+ uses: GeyserMC/actions/.github/workflows/upload-preview.yml@master
with:
build: ${{ github.run_number }}
- version: pr.${{ github.event.pull_request.number }}
\ No newline at end of file
+ version: pr.${{ github.event.pull_request.number }}
+ files: |
+ bungeecord:Geyser-BungeeCord.jar
+ fabric:Geyser-Fabric.jar
+ neoforge:Geyser-NeoForge.jar
+ spigot:Geyser-Spigot.jar
+ standalone:Geyser-Standalone.jar
+ velocity:Geyser-Velocity.jar
+ viaproxy:Geyser-ViaProxy.jar
+ project: geyserpreview
+ runId: ${{ github.run_id }}
\ No newline at end of file
diff --git a/README.md b/README.md
index 9257af9ac..dd2d096ec 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!
-### Currently supporting Minecraft Bedrock 1.20.40 - 1.20.80/81 and Minecraft Java 1.20.5/1.20.6
+### Currently supporting Minecraft Bedrock 1.20.80 - 1.21.0 and Minecraft Java 1.20.5/1.20.6
## Setting Up
Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser.
diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraData.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraData.java
index 2f715fa1e..f208879d1 100644
--- a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraData.java
+++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraData.java
@@ -145,4 +145,36 @@ public interface CameraData {
* @return whether the camera is currently locked
*/
boolean isCameraLocked();
-}
\ No newline at end of file
+
+ /**
+ * Hides a {@link GuiElement} on the client's side.
+ *
+ * @param element the {@link GuiElement} to hide
+ */
+ void hideElement(@NonNull GuiElement... element);
+
+ /**
+ * Resets a {@link GuiElement} on the client's side.
+ * This makes the client decide on its own - e.g. based on client settings -
+ * whether to show or hide the gui element.
+ *
+ * If no elements are specified, this will reset all currently hidden elements
+ *
+ * @param element the {@link GuiElement} to reset
+ */
+ void resetElement(@NonNull GuiElement @Nullable... element);
+
+ /**
+ * Determines whether a {@link GuiElement} is currently hidden.
+ *
+ * @param element the {@link GuiElement} to check
+ */
+ boolean isHudElementHidden(@NonNull GuiElement element);
+
+ /**
+ * Returns the currently hidden {@link GuiElement}s.
+ *
+ * @return an unmodifiable view of all currently hidden {@link GuiElement}s
+ */
+ @NonNull Set hiddenElements();
+}
diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/GuiElement.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/GuiElement.java
new file mode 100644
index 000000000..4d3653648
--- /dev/null
+++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/GuiElement.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.api.bedrock.camera;
+
+/**
+ * Represent GUI elements on the players HUD display.
+ * These can be hidden using {@link CameraData#hideElement(GuiElement...)},
+ * and one can reset their visibility using {@link CameraData#resetElement(GuiElement...)}.
+ */
+public class GuiElement {
+ public static final GuiElement PAPER_DOLL = new GuiElement(0);
+ public static final GuiElement ARMOR = new GuiElement(1);
+ public static final GuiElement TOOL_TIPS = new GuiElement(2);
+ public static final GuiElement TOUCH_CONTROLS = new GuiElement(3);
+ public static final GuiElement CROSSHAIR = new GuiElement(4);
+ public static final GuiElement HOTBAR = new GuiElement(5);
+ public static final GuiElement HEALTH = new GuiElement(6);
+ public static final GuiElement PROGRESS_BAR = new GuiElement(7);
+ public static final GuiElement FOOD_BAR = new GuiElement(8);
+ public static final GuiElement AIR_BUBBLES_BAR = new GuiElement(9);
+ public static final GuiElement VEHICLE_HEALTH = new GuiElement(10);
+ public static final GuiElement EFFECTS_BAR = new GuiElement(11);
+ public static final GuiElement ITEM_TEXT_POPUP = new GuiElement(12);
+
+ private GuiElement(int id) {
+ this.id = id;
+ }
+
+ private final int id;
+
+ /**
+ * Internal use only; don't depend on these values being consistent.
+ */
+ public int id() {
+ return this.id;
+ }
+}
diff --git a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java
index 522562d11..86a5ec6f8 100644
--- a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java
+++ b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionLoginEvent.java
@@ -36,7 +36,7 @@ import java.util.Map;
import java.util.Objects;
/**
- * Called when a session has logged in, and is about to connect to a remote java server.
+ * Called when a session has logged in, and is about to connect to a remote Java server.
* This event is cancellable, and can be used to prevent the player from connecting to the remote server.
*/
public final class SessionLoginEvent extends ConnectionEvent implements Cancellable {
@@ -99,9 +99,9 @@ public final class SessionLoginEvent extends ConnectionEvent implements Cancella
}
/**
- * Gets the {@link RemoteServer} the section will attempt to connect to.
+ * Gets the {@link RemoteServer} the session will attempt to connect to.
*
- * @return the {@link RemoteServer} the section will attempt to connect to.
+ * @return the {@link RemoteServer} the session will attempt to connect to.
*/
public @NonNull RemoteServer remoteServer() {
return this.remoteServer;
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java
index daeb20102..e8cf7ee39 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java
@@ -26,22 +26,19 @@
package org.geysermc.geyser.platform.bungeecord;
import lombok.Getter;
+import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.geysermc.geyser.GeyserLogger;
import java.util.logging.Level;
import java.util.logging.Logger;
+@RequiredArgsConstructor
public class GeyserBungeeLogger implements GeyserLogger {
private final Logger logger;
@Getter @Setter
private boolean debug;
- public GeyserBungeeLogger(Logger logger, boolean debug) {
- this.logger = logger;
- this.debug = debug;
- }
-
@Override
public void severe(String message) {
logger.severe(message);
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
index 4191c8578..062ef6f76 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
@@ -58,14 +58,13 @@ import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
private GeyserCommandManager geyserCommandManager;
private GeyserBungeeConfiguration geyserConfig;
private GeyserBungeeInjector geyserInjector;
- private GeyserBungeeLogger geyserLogger;
+ private final GeyserBungeeLogger geyserLogger = new GeyserBungeeLogger(getLogger());
private IGeyserPingPassthrough geyserBungeePingPassthrough;
private GeyserImpl geyser;
@@ -82,21 +81,21 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
// Copied from ViaVersion.
// https://github.com/ViaVersion/ViaVersion/blob/b8072aad86695cc8ec6f5e4103e43baf3abf6cc5/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java#L43
try {
- ProtocolConstants.class.getField("MINECRAFT_1_20_3");
+ ProtocolConstants.class.getField("MINECRAFT_1_20_5");
} catch (NoSuchFieldException e) {
- getLogger().warning(" / \\");
- getLogger().warning(" / \\");
- getLogger().warning(" / | \\");
- getLogger().warning(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName()));
- getLogger().warning(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
- getLogger().warning(" / o \\");
- getLogger().warning("/_____________\\");
+ geyserLogger.error(" / \\");
+ geyserLogger.error(" / \\");
+ geyserLogger.error(" / | \\");
+ geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName()));
+ geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
+ geyserLogger.error(" / o \\");
+ geyserLogger.error("/_____________\\");
}
if (!this.loadConfig()) {
return;
}
- this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode());
+ this.geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
this.geyser = GeyserImpl.load(PlatformType.BUNGEECORD, this);
this.geyserInjector = new GeyserBungeeInjector(this);
@@ -293,7 +292,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class);
} catch (IOException ex) {
- getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
return false;
}
diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java
index 786faac93..d7373f0a9 100644
--- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java
+++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModBootstrap.java
@@ -34,7 +34,6 @@ import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player;
-import org.apache.logging.log4j.LogManager;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserBootstrap;
@@ -80,7 +79,7 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap {
private GeyserCommandManager geyserCommandManager;
private GeyserModConfiguration geyserConfig;
private GeyserModInjector geyserInjector;
- private GeyserModLogger geyserLogger;
+ private final GeyserModLogger geyserLogger = new GeyserModLogger();
private IGeyserPingPassthrough geyserPingPassthrough;
private WorldManager geyserWorldManager;
@@ -92,7 +91,7 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap {
if (!loadConfig()) {
return;
}
- this.geyserLogger = new GeyserModLogger(geyserConfig.isDebugMode());
+ this.geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
this.geyser = GeyserImpl.load(this.platform.platformType(), this);
@@ -288,7 +287,7 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap {
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserModConfiguration.class);
return true;
} catch (IOException ex) {
- LogManager.getLogger("geyser").error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
return false;
}
diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java
index 444b725e9..9260288d7 100644
--- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java
+++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java
@@ -37,10 +37,6 @@ public class GeyserModLogger implements GeyserLogger {
private boolean debug;
- public GeyserModLogger(boolean isDebug) {
- debug = isDebug;
- }
-
@Override
public void severe(String message) {
logger.fatal(message);
diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java
index 656305690..5543dbcee 100644
--- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java
+++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/world/GeyserModWorldManager.java
@@ -25,13 +25,7 @@
package org.geysermc.geyser.platform.mod.world;
-import org.geysermc.mcprotocollib.protocol.data.game.Holder;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
-import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
@@ -39,33 +33,25 @@ import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
-import net.minecraft.server.network.Filterable;
import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.component.WritableBookContent;
-import net.minecraft.world.item.component.WrittenBookContent;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BannerBlockEntity;
import net.minecraft.world.level.block.entity.BannerPatternLayers;
import net.minecraft.world.level.block.entity.BlockEntity;
-import net.minecraft.world.level.block.entity.LecternBlockEntity;
import net.minecraft.world.level.chunk.ChunkAccess;
-import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import org.checkerframework.checker.nullness.qual.NonNull;
-import org.cloudburstmc.math.vector.Vector3i;
-import org.cloudburstmc.nbt.NbtMap;
-import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.cloudburstmc.nbt.NbtType;
-import org.geysermc.erosion.util.LecternUtils;
import org.geysermc.geyser.level.GeyserWorldManager;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.platform.mod.GeyserModBootstrap;
import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.util.BlockEntityUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.Holder;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -73,7 +59,6 @@ import java.util.concurrent.CompletableFuture;
public class GeyserModWorldManager extends GeyserWorldManager {
private static final GsonComponentSerializer GSON_SERIALIZER = GsonComponentSerializer.gson();
- private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.legacySection();
private final MinecraftServer server;
public GeyserModWorldManager(MinecraftServer server) {
@@ -121,94 +106,6 @@ public class GeyserModWorldManager extends GeyserWorldManager {
return SharedConstants.getCurrentVersion().getProtocolVersion() == GameProtocol.getJavaProtocolVersion();
}
- @Override
- public boolean shouldExpectLecternHandled(GeyserSession session) {
- return true;
- }
-
- @Override
- public void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos) {
- server.execute(() -> {
- ServerPlayer player = getPlayer(session);
- if (player == null) {
- return;
- }
-
- //noinspection resource - level() is just a getter
- LevelChunk chunk = player.level().getChunk(x, z);
- final int chunkBlockX = x << 4;
- final int chunkBlockZ = z << 4;
- //noinspection ForLoopReplaceableByForEach - avoid constructing iterator
- for (int i = 0; i < blockEntityInfos.size(); i++) {
- BlockEntityInfo blockEntityInfo = blockEntityInfos.get(i);
- BlockEntity blockEntity = chunk.getBlockEntity(new BlockPos(chunkBlockX + blockEntityInfo.getX(),
- blockEntityInfo.getY(), chunkBlockZ + blockEntityInfo.getZ()));
- sendLecternData(session, blockEntity, true);
- }
- });
- }
-
- @Override
- public void sendLecternData(GeyserSession session, int x, int y, int z) {
- server.execute(() -> {
- ServerPlayer player = getPlayer(session);
- if (player == null) {
- return;
- }
- //noinspection resource - level() is just a getter
- BlockEntity blockEntity = player.level().getBlockEntity(new BlockPos(x, y, z));
- sendLecternData(session, blockEntity, false);
- });
- }
-
- private void sendLecternData(GeyserSession session, BlockEntity blockEntity, boolean isChunkLoad) {
- if (!(blockEntity instanceof LecternBlockEntity lectern)) {
- return;
- }
-
- int x = blockEntity.getBlockPos().getX();
- int y = blockEntity.getBlockPos().getY();
- int z = blockEntity.getBlockPos().getZ();
-
- if (!lectern.hasBook()) {
- if (!isChunkLoad) {
- BlockEntityUtils.updateBlockEntity(session, LecternUtils.getBaseLecternTag(x, y, z, 0).build(), Vector3i.from(x, y, z));
- }
- return;
- }
-
- ItemStack book = lectern.getBook();
- int pageCount = getPageCount(book);
- boolean hasBookPages = pageCount > 0;
- NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(x, y, z, hasBookPages ? pageCount : 1);
- lecternTag.putInt("page", lectern.getPage() / 2);
- NbtMapBuilder bookTag = NbtMap.builder()
- .putByte("Count", (byte) book.getCount())
- .putShort("Damage", (short) 0)
- .putString("Name", "minecraft:writable_book");
- List pages = new ArrayList<>(hasBookPages ? pageCount : 1);
- if (hasBookPages) {
- List bookPages = getPages(book);
- for (String page : bookPages) {
- NbtMapBuilder pageBuilder = NbtMap.builder()
- .putString("photoname", "")
- .putString("text", page);
- pages.add(pageBuilder.build());
- }
- } else {
- // Empty page
- NbtMapBuilder pageBuilder = NbtMap.builder()
- .putString("photoname", "")
- .putString("text", "");
- pages.add(pageBuilder.build());
- }
-
- bookTag.putCompound("tag", NbtMap.builder().putList("pages", NbtType.COMPOUND, pages).build());
- lecternTag.putCompound("book", bookTag.build());
- NbtMap blockEntityTag = lecternTag.build();
- BlockEntityUtils.updateBlockEntity(session, blockEntityTag, Vector3i.from(x, y, z));
- }
-
@Override
public boolean hasPermission(GeyserSession session, String permission) {
ServerPlayer player = getPlayer(session);
@@ -267,39 +164,6 @@ public class GeyserModWorldManager extends GeyserWorldManager {
return server.getPlayerList().getPlayer(session.getPlayerEntity().getUuid());
}
- private static int getPageCount(ItemStack itemStack) {
- WrittenBookContent writtenBookContent = itemStack.get(DataComponents.WRITTEN_BOOK_CONTENT);
- if (writtenBookContent != null) {
- return writtenBookContent.pages().size();
- } else {
- WritableBookContent writableBookContent = itemStack.get(DataComponents.WRITABLE_BOOK_CONTENT);
- return writableBookContent != null ? writableBookContent.pages().size() : 0;
- }
- }
-
- private static List getPages(ItemStack itemStack) {
- WrittenBookContent writtenBookContent = itemStack.get(DataComponents.WRITTEN_BOOK_CONTENT);
- if (writtenBookContent != null) {
- return writtenBookContent.pages().stream()
- .map(Filterable::raw)
- .map(GeyserModWorldManager::fromComponent)
- .toList();
- } else {
- WritableBookContent writableBookContent = itemStack.get(DataComponents.WRITABLE_BOOK_CONTENT);
- if (writableBookContent == null) {
- return List.of();
- }
- return writableBookContent.pages().stream()
- .map(Filterable::raw)
- .toList();
- }
- }
-
- private static String fromComponent(Component component) {
- String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY);
- return LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty()));
- }
-
private static net.kyori.adventure.text.Component toKyoriComponent(Component component) {
String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY);
return GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty());
diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts
index e7503b964..831cd27ae 100644
--- a/bootstrap/spigot/build.gradle.kts
+++ b/bootstrap/spigot/build.gradle.kts
@@ -4,6 +4,12 @@ dependencies {
isTransitive = false
}
+ implementation(libs.erosion.bukkit.nms) {
+ attributes {
+ attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
+ }
+ }
+
implementation(variantOf(libs.adapters.spigot) {
classifier("all") // otherwise the unshaded jar is used without the shaded NMS implementations
})
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java
index 930f84cec..9ebd6519a 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java
@@ -34,8 +34,8 @@ import java.util.logging.Logger;
public final class GeyserPaperLogger extends GeyserSpigotLogger {
private final ComponentLogger componentLogger;
- public GeyserPaperLogger(Plugin plugin, Logger logger, boolean debug) {
- super(logger, debug);
+ public GeyserPaperLogger(Plugin plugin, Logger logger) {
+ super(logger);
componentLogger = plugin.getComponentLogger();
}
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java
index fe56cba1c..5c6101eae 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java
@@ -25,15 +25,15 @@
package org.geysermc.geyser.platform.spigot;
-import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.geysermc.geyser.GeyserLogger;
import java.util.logging.Level;
import java.util.logging.Logger;
-@AllArgsConstructor
+@RequiredArgsConstructor
public class GeyserSpigotLogger implements GeyserLogger {
private final Logger logger;
@Getter @Setter
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
index 293b0ce3f..ec731d00c 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
@@ -81,14 +81,14 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
-import java.util.logging.Level;
public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
private GeyserSpigotCommandManager geyserCommandManager;
private GeyserSpigotConfiguration geyserConfig;
private GeyserSpigotInjector geyserInjector;
- private GeyserSpigotLogger geyserLogger;
+ private final GeyserSpigotLogger geyserLogger = GeyserPaperLogger.supported() ?
+ new GeyserPaperLogger(this, getLogger()) : new GeyserSpigotLogger(getLogger());
private IGeyserPingPassthrough geyserSpigotPingPassthrough;
private GeyserSpigotWorldManager geyserWorldManager;
@@ -116,12 +116,12 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
// We depend on this as a fallback in certain scenarios
BlockData.class.getMethod("getAsString");
} catch (ClassNotFoundException | NoSuchMethodException e) {
- getLogger().severe("*********************************************");
- getLogger().severe("");
- getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.header"));
- getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.13.2"));
- getLogger().severe("");
- getLogger().severe("*********************************************");
+ geyserLogger.error("*********************************************");
+ geyserLogger.error("");
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.header"));
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.13.2"));
+ geyserLogger.error("");
+ geyserLogger.error("*********************************************");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
@@ -130,12 +130,12 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
Class.forName("net.md_5.bungee.chat.ComponentSerializer");
} catch (ClassNotFoundException e) {
if (!PaperAdventure.canSendMessageUsingComponent()) { // Prepare for Paper eventually removing Bungee chat
- getLogger().severe("*********************************************");
- getLogger().severe("");
- getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.header", getServer().getName()));
- getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.message", "Paper"));
- getLogger().severe("");
- getLogger().severe("*********************************************");
+ geyserLogger.error("*********************************************");
+ geyserLogger.error("");
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.header", getServer().getName()));
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.message", "Paper"));
+ geyserLogger.error("");
+ geyserLogger.error("*********************************************");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
@@ -144,11 +144,11 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
try {
Class.forName("io.netty.util.internal.ObjectPool$ObjectCreator");
} catch (ClassNotFoundException e) {
- getLogger().severe("*********************************************");
- getLogger().severe("");
- getLogger().severe("This version of Spigot is using an outdated version of netty. Please use Paper instead!");
- getLogger().severe("");
- getLogger().severe("*********************************************");
+ geyserLogger.error("*********************************************");
+ geyserLogger.error("");
+ geyserLogger.error("This version of Spigot is using an outdated version of netty. Please use Paper instead!");
+ geyserLogger.error("");
+ geyserLogger.error("*********************************************");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
@@ -156,8 +156,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
if (!loadConfig()) {
return;
}
- this.geyserLogger = GeyserPaperLogger.supported() ? new GeyserPaperLogger(this, getLogger(), geyserConfig.isDebugMode())
- : new GeyserSpigotLogger(getLogger(), geyserConfig.isDebugMode());
+ this.geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
// Turn "(MC: 1.16.4)" into 1.16.4.
@@ -268,7 +267,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
this.geyserWorldManager = new GeyserSpigotNativeWorldManager(this, isPaper);
}
geyserLogger.debug("Using world manager of type: " + this.geyserWorldManager.getClass().getSimpleName());
- } catch (Exception e) {
+ } catch (Throwable e) {
if (geyserConfig.isDebugMode()) {
geyserLogger.debug("Error while attempting to find NMS adapter. Most likely, this can be safely ignored. :)");
e.printStackTrace();
@@ -489,7 +488,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class);
ConfigLoaderTemp.load(GeyserPluginConfig.class);
} catch (IOException ex) {
- getLogger().log(Level.SEVERE, GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
Bukkit.getPluginManager().disablePlugin(this);
return false;
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java
index 61c0d5fe8..963f5bac3 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserPistonListener.java
@@ -25,10 +25,8 @@
package org.geysermc.geyser.platform.spigot.world;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
-import org.cloudburstmc.math.vector.Vector3i;
-import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@@ -40,13 +38,17 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPistonEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
+import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.PistonCache;
import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity;
+import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
import java.util.List;
import java.util.Map;
@@ -85,7 +87,7 @@ public class GeyserPistonListener implements Listener {
PistonValueType type = isExtend ? PistonValueType.PUSHING : PistonValueType.PULLING;
boolean sticky = event.isSticky();
- Object2IntMap attachedBlocks = new Object2IntArrayMap<>();
+ Object2ObjectMap attachedBlocks = new Object2ObjectArrayMap<>();
boolean blocksFilled = false;
for (Map.Entry entry : geyser.getSessionManager().getSessions().entrySet()) {
@@ -108,10 +110,10 @@ public class GeyserPistonListener implements Listener {
List blocks = isExtend ? ((BlockPistonExtendEvent) event).getBlocks() : ((BlockPistonRetractEvent) event).getBlocks();
for (Block block : blocks) {
Location attachedLocation = block.getLocation();
- int blockId = worldManager.getBlockNetworkId(block);
+ BlockState state = BlockState.of(worldManager.getBlockNetworkId(block));
// Ignore blocks that will be destroyed
- if (BlockStateValues.canPistonMoveBlock(blockId, isExtend)) {
- attachedBlocks.put(getVector(attachedLocation), blockId);
+ if (BlockStateValues.canPistonMoveBlock(state, isExtend)) {
+ attachedBlocks.put(getVector(attachedLocation), state);
}
}
blocksFilled = true;
@@ -119,7 +121,7 @@ public class GeyserPistonListener implements Listener {
int pistonBlockId = worldManager.getBlockNetworkId(event.getBlock());
// event.getDirection() is unreliable
- Direction orientation = BlockStateValues.getPistonOrientation(pistonBlockId);
+ Direction orientation = BlockState.of(pistonBlockId).getValue(Properties.FACING);
session.executeInEventLoop(() -> {
PistonCache pistonCache = session.getPistonCache();
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java
index 71aba11f9..1cdd77c64 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java
@@ -33,7 +33,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
@@ -59,11 +59,11 @@ public class GeyserSpigotBlockPlaceListener implements Listener {
event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ())));
} else {
String javaBlockId = event.getBlockPlaced().getBlockData().getAsString();
- placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(javaBlockId, BlockStateValues.JAVA_AIR_ID)));
+ placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(javaBlockId, Block.JAVA_AIR_ID)));
}
placeBlockSoundPacket.setIdentifier(":");
session.sendUpstreamPacket(placeBlockSoundPacket);
session.setLastBlockPlacePosition(null);
- session.setLastBlockPlacedId(null);
+ session.setLastBlockPlaced(null);
}
}
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java
index 45e84d254..c99ca4e78 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotNativeWorldManager.java
@@ -34,6 +34,7 @@ import org.geysermc.geyser.adapters.WorldAdapter;
import org.geysermc.geyser.adapters.paper.PaperAdapters;
import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession;
public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
@@ -52,7 +53,7 @@ public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
public int getBlockAt(GeyserSession session, int x, int y, int z) {
Player player = Bukkit.getPlayer(session.getPlayerEntity().getUsername());
if (player == null) {
- return BlockStateValues.JAVA_AIR_ID;
+ return Block.JAVA_AIR_ID;
}
return adapter.getBlockAt(player.getWorld(), x, y, z);
}
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java
index 8a0e0b70d..e247a72c7 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java
@@ -25,30 +25,24 @@
package org.geysermc.geyser.platform.spigot.world.manager;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.bukkit.Bukkit;
-import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
-import org.cloudburstmc.nbt.NbtMap;
-import org.geysermc.erosion.bukkit.BukkitLecterns;
-import org.geysermc.erosion.bukkit.BukkitUtils;
+import org.geysermc.erosion.bukkit.PickBlockUtils;
import org.geysermc.erosion.bukkit.SchedulerUtils;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.GameRule;
import org.geysermc.geyser.level.WorldManager;
-import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.util.BlockEntityUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@@ -57,23 +51,21 @@ import java.util.concurrent.CompletableFuture;
*/
public class GeyserSpigotWorldManager extends WorldManager {
private final Plugin plugin;
- private final BukkitLecterns lecterns;
public GeyserSpigotWorldManager(Plugin plugin) {
this.plugin = plugin;
- this.lecterns = new BukkitLecterns(plugin);
}
@Override
public int getBlockAt(GeyserSession session, int x, int y, int z) {
Player bukkitPlayer;
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
- return BlockStateValues.JAVA_AIR_ID;
+ return org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID;
}
World world = bukkitPlayer.getWorld();
if (!world.isChunkLoaded(x >> 4, z >> 4)) {
// If the chunk isn't loaded, how could we even be here?
- return BlockStateValues.JAVA_AIR_ID;
+ return org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID;
}
return getBlockNetworkId(world.getBlockAt(x, y, z));
@@ -84,9 +76,9 @@ public class GeyserSpigotWorldManager extends WorldManager {
// Terrible behavior, but this is basically what's always been happening behind the scenes anyway.
CompletableFuture blockData = new CompletableFuture<>();
Bukkit.getRegionScheduler().execute(this.plugin, block.getLocation(), () -> blockData.complete(block.getBlockData().getAsString()));
- return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), BlockStateValues.JAVA_AIR_ID);
+ return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID);
}
- return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), BlockStateValues.JAVA_AIR_ID);
+ return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID); // TODO could just make this a BlockState lookup?
}
@Override
@@ -94,69 +86,6 @@ public class GeyserSpigotWorldManager extends WorldManager {
return true;
}
- @Override
- public void sendLecternData(GeyserSession session, int x, int y, int z) {
- Player bukkitPlayer;
- if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
- return;
- }
-
- Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z);
- // Run as a task to prevent async issues
- SchedulerUtils.runTask(this.plugin, () -> sendLecternData(session, block, false), block);
- }
-
- public void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos) {
- Player bukkitPlayer;
- if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
- return;
- }
- if (SchedulerUtils.FOLIA) {
- Chunk chunk = getChunk(bukkitPlayer.getWorld(), x, z);
- if (chunk == null) {
- return;
- }
- Bukkit.getRegionScheduler().execute(this.plugin, bukkitPlayer.getWorld(), x, z, () ->
- sendLecternData(session, chunk, blockEntityInfos));
- } else {
- Bukkit.getScheduler().runTask(this.plugin, () -> {
- Chunk chunk = getChunk(bukkitPlayer.getWorld(), x, z);
- if (chunk == null) {
- return;
- }
- sendLecternData(session, chunk, blockEntityInfos);
- });
- }
- }
-
- private @Nullable Chunk getChunk(World world, int x, int z) {
- if (!world.isChunkLoaded(x, z)) {
- return null;
- }
- return world.getChunkAt(x, z);
- }
-
- private void sendLecternData(GeyserSession session, Chunk chunk, List blockEntityInfos) {
- //noinspection ForLoopReplaceableByForEach - avoid constructing Iterator
- for (int i = 0; i < blockEntityInfos.size(); i++) {
- BlockEntityInfo info = blockEntityInfos.get(i);
- Block block = chunk.getBlock(info.getX(), info.getY(), info.getZ());
- sendLecternData(session, block, true);
- }
- }
-
- private void sendLecternData(GeyserSession session, Block block, boolean isChunkLoad) {
- NbtMap blockEntityTag = this.lecterns.getLecternData(block, isChunkLoad);
- if (blockEntityTag != null) {
- BlockEntityUtils.updateBlockEntity(session, blockEntityTag, BukkitUtils.getVector(block.getLocation()));
- }
- }
-
- @Override
- public boolean shouldExpectLecternHandled(GeyserSession session) {
- return true;
- }
-
public boolean getGameRuleBool(GeyserSession session, GameRule gameRule) {
org.bukkit.GameRule> bukkitGameRule = org.bukkit.GameRule.getByName(gameRule.getJavaID());
if (bukkitGameRule == null) {
@@ -205,17 +134,16 @@ public class GeyserSpigotWorldManager extends WorldManager {
@Override
public @NonNull CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
- CompletableFuture<@Nullable DataComponents> future = new CompletableFuture<>();
Player bukkitPlayer;
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
- future.complete(null);
- return future;
+ return CompletableFuture.completedFuture(null);
}
+ CompletableFuture> future = new CompletableFuture<>();
Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z);
// Paper 1.19.3 complains about async access otherwise.
// java.lang.IllegalStateException: Tile is null, asynchronous access?
- SchedulerUtils.runTask(this.plugin, () -> future.complete(/*PickBlockUtils.pickBlock(block)*/ null), block); // TODO fix erosion once clear how to handle this
- return future;
+ SchedulerUtils.runTask(this.plugin, () -> future.complete(PickBlockUtils.pickBlock(block)), block);
+ return future.thenApply(RAW_TRANSFORMER);
}
/**
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
index a2b701665..98b67a32b 100644
--- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
+++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
@@ -68,7 +68,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
private GeyserCommandManager geyserCommandManager;
private GeyserStandaloneConfiguration geyserConfig;
- private GeyserStandaloneLogger geyserLogger;
+ private final GeyserStandaloneLogger geyserLogger = new GeyserStandaloneLogger();
private IGeyserPingPassthrough geyserPingPassthrough;
private GeyserStandaloneGUI gui;
@Getter
@@ -178,8 +178,6 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
}
}
- this.geyserLogger = new GeyserStandaloneLogger();
-
if (useGui && gui == null) {
gui = new GeyserStandaloneGUI(geyserLogger);
gui.redirectSystemStreams();
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java
index 567870e7f..4d10e4daf 100644
--- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java
+++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java
@@ -25,13 +25,13 @@
package org.geysermc.geyser.platform.velocity;
-import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.geysermc.geyser.GeyserLogger;
import org.slf4j.Logger;
-@AllArgsConstructor
+@RequiredArgsConstructor
public class GeyserVelocityLogger implements GeyserLogger {
private final Logger logger;
@Getter @Setter
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java
index 347a47d63..539bdadbf 100644
--- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java
+++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java
@@ -64,44 +64,44 @@ import java.util.UUID;
@Plugin(id = "geyser", name = GeyserImpl.NAME + "-Velocity", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
public class GeyserVelocityPlugin implements GeyserBootstrap {
- @Inject
- private Logger logger;
-
- @Inject
- private ProxyServer proxyServer;
-
- @Inject
- private CommandManager commandManager;
+ private final ProxyServer proxyServer;
+ private final CommandManager commandManager;
+ private final GeyserVelocityLogger geyserLogger;
private GeyserCommandManager geyserCommandManager;
private GeyserVelocityConfiguration geyserConfig;
private GeyserVelocityInjector geyserInjector;
- private GeyserVelocityLogger geyserLogger;
private IGeyserPingPassthrough geyserPingPassthrough;
-
private GeyserImpl geyser;
@Getter
private final Path configFolder = Paths.get("plugins/" + GeyserImpl.NAME + "-Velocity/");
+ @Inject
+ public GeyserVelocityPlugin(ProxyServer server, Logger logger, CommandManager manager) {
+ this.geyserLogger = new GeyserVelocityLogger(logger);
+ this.proxyServer = server;
+ this.commandManager = manager;
+ }
+
@Override
public void onGeyserInitialize() {
GeyserLocale.init(this);
if (!ProtocolVersion.isSupported(GameProtocol.getJavaProtocolVersion())) {
- logger.error(" / \\");
- logger.error(" / \\");
- logger.error(" / | \\");
- logger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", proxyServer.getVersion().getName()));
- logger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
- logger.error(" / o \\");
- logger.error("/_____________\\");
+ geyserLogger.error(" / \\");
+ geyserLogger.error(" / \\");
+ geyserLogger.error(" / | \\");
+ geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", proxyServer.getVersion().getName()));
+ geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
+ geyserLogger.error(" / o \\");
+ geyserLogger.error("/_____________\\");
}
if (!loadConfig()) {
return;
}
- this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode());
+ this.geyserLogger.setDebug(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
this.geyser = GeyserImpl.load(PlatformType.VELOCITY, this);
@@ -249,7 +249,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
"config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class);
} catch (IOException ex) {
- logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
+ geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
return false;
}
diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java
index bf9d6816c..afc46fa6a 100644
--- a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java
+++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyConfiguration.java
@@ -27,14 +27,23 @@ package org.geysermc.geyser.platform.viaproxy;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.viaproxy.ViaProxy;
+import net.raphimc.viaproxy.protocoltranslator.viaproxy.ViaProxyConfig;
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
import java.io.File;
import java.nio.file.Path;
@JsonIgnoreProperties(ignoreUnknown = true)
+@SuppressWarnings("FieldMayBeFinal") // Jackson requires that the fields are not final
public class GeyserViaProxyConfiguration extends GeyserJacksonConfiguration {
+ private RemoteConfiguration remote = new RemoteConfiguration() {
+ @Override
+ public boolean isForwardHost() {
+ return super.isForwardHost() || !ViaProxy.getConfig().getWildcardDomainHandling().equals(ViaProxyConfig.WildcardDomainHandling.NONE);
+ }
+ };
+
@Override
public Path getFloodgateKeyPath() {
return new File(GeyserViaProxyPlugin.ROOT_FOLDER, this.getFloodgateKeyFile()).toPath();
@@ -50,4 +59,9 @@ public class GeyserViaProxyConfiguration extends GeyserJacksonConfiguration {
return interval;
}
+ @Override
+ public RemoteConfiguration getRemote() {
+ return this.remote;
+ }
+
}
diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java
index 30404e705..bdc80335a 100644
--- a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java
+++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/GeyserViaProxyPlugin.java
@@ -37,6 +37,7 @@ import org.apache.logging.log4j.LogManager;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger;
+import org.geysermc.geyser.api.event.EventRegistrar;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandManager;
@@ -44,6 +45,7 @@ import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
+import org.geysermc.geyser.platform.viaproxy.listener.GeyserServerTransferListener;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.FileUtils;
@@ -57,7 +59,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
-public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootstrap {
+public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootstrap, EventRegistrar {
public static final File ROOT_FOLDER = new File(PluginManager.PLUGINS_DIR, "Geyser");
@@ -120,6 +122,7 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst
}
this.geyser = GeyserImpl.load(PlatformType.VIAPROXY, this);
+ this.geyser.eventBus().register(this, new GeyserServerTransferListener());
LoopbackUtil.checkAndApplyLoopback(this.logger);
}
diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/listener/GeyserServerTransferListener.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/listener/GeyserServerTransferListener.java
new file mode 100644
index 000000000..64b3cc56e
--- /dev/null
+++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/listener/GeyserServerTransferListener.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.platform.viaproxy.listener;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.net.HostAndPort;
+import org.geysermc.event.PostOrder;
+import org.geysermc.event.subscribe.Subscribe;
+import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent;
+import org.geysermc.geyser.api.event.java.ServerTransferEvent;
+import org.geysermc.geyser.session.GeyserSession;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public class GeyserServerTransferListener {
+
+ private final Cache> cookieStorages = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build();
+
+ @Subscribe(postOrder = PostOrder.FIRST)
+ private void onServerTransfer(final ServerTransferEvent event) {
+ this.cookieStorages.put(event.connection().xuid(), event.cookies());
+ final GeyserSession geyserSession = (GeyserSession) event.connection();
+ final HostAndPort hostAndPort = HostAndPort.fromString(geyserSession.getClientData().getServerAddress()).withDefaultPort(19132);
+ event.bedrockHost(hostAndPort.getHost());
+ event.bedrockPort(hostAndPort.getPort());
+ }
+
+ @Subscribe(postOrder = PostOrder.FIRST)
+ private void onSessionLogin(final SessionLoginEvent event) {
+ final Map cookies = this.cookieStorages.asMap().remove(event.connection().xuid());
+ if (cookies != null) {
+ event.cookies(cookies);
+ event.transferring(true);
+ }
+ }
+
+}
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index c8bc432df..5072a1550 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -27,7 +27,6 @@ dependencies {
implementation(libs.websocket)
api(libs.bundles.protocol)
- implementation(libs.blockstateupdater)
api(libs.mcauthlib)
api(libs.mcprotocollib) {
diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
index 8afe2d9e6..88249ed5b 100644
--- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
+++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java
@@ -47,6 +47,7 @@ import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.geysermc.api.Geyser;
import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormBuilder;
+import org.geysermc.erosion.packet.Packets;
import org.geysermc.floodgate.crypto.AesCipher;
import org.geysermc.floodgate.crypto.AesKeyProducer;
import org.geysermc.floodgate.crypto.Base64Topping;
@@ -79,6 +80,7 @@ import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
import org.geysermc.geyser.session.SessionManager;
+import org.geysermc.geyser.session.cache.RegistryCache;
import org.geysermc.geyser.skin.FloodgateSkinUploader;
import org.geysermc.geyser.skin.ProvidedSkins;
import org.geysermc.geyser.skin.SkinProvider;
@@ -217,6 +219,8 @@ public class GeyserImpl implements GeyserApi {
Registries.init();
BlockRegistries.init();
+ RegistryCache.init();
+
/* Initialize translators */
EntityDefinitions.init();
MessageTranslator.init();
@@ -389,7 +393,7 @@ public class GeyserImpl implements GeyserApi {
this.newsHandler = new NewsHandler(BRANCH, this.buildNumber());
- //Packets.initGeyser();
+ Packets.initGeyser();
if (Epoll.isAvailable()) {
this.erosionUnixListener = new UnixSocketClientListener();
@@ -772,6 +776,7 @@ public class GeyserImpl implements GeyserApi {
return 0;
}
+ //noinspection DataFlowIssue
return Integer.parseInt(BUILD_NUMBER);
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
index a3f16875d..6267ee791 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/Entity.java
@@ -137,7 +137,7 @@ public class Entity implements GeyserEntity {
this.valid = false;
- this.propertyManager = new GeyserEntityPropertyManager(definition.registeredProperties());
+ this.propertyManager = definition.registeredProperties() == null ? null : new GeyserEntityPropertyManager(definition.registeredProperties());
setPosition(position);
setAirSupply(getMaxAir());
@@ -364,7 +364,7 @@ public class Entity implements GeyserEntity {
return;
}
- if (propertyManager.hasProperties()) {
+ if (propertyManager != null && propertyManager.hasProperties()) {
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(geyserId);
propertyManager.applyIntProperties(entityDataPacket.getProperties().getIntProperties());
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
index f4c0cea36..26a64bcae 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/FishingHookEntity.java
@@ -33,6 +33,7 @@ import org.geysermc.erosion.util.BlockPositionIterator;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.collision.BlockCollision;
@@ -162,7 +163,7 @@ public class FishingHookEntity extends ThrowableEntity {
*/
protected boolean isInAir() {
int block = session.getGeyser().getWorldManager().getBlockAt(session, position.toInt());
- return block == BlockStateValues.JAVA_AIR_ID;
+ return block == Block.JAVA_AIR_ID;
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java
index ef584c4fd..e33e6d7b6 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/FurnaceMinecartEntity.java
@@ -25,14 +25,16 @@
package org.geysermc.geyser.entity.type;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import java.util.UUID;
@@ -51,7 +53,8 @@ public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity {
@Override
public void updateDefaultBlockMetadata() {
- dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(hasFuel ? BlockStateValues.JAVA_FURNACE_LIT_ID : BlockStateValues.JAVA_FURNACE_ID));
+ BlockState furnace = Blocks.FURNACE.defaultBlockState().withValue(Properties.LIT, hasFuel);
+ dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(furnace));
dirtyMetadata.put(EntityDataTypes.DISPLAY_OFFSET, 6);
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java
index ead717b34..49eb9ddc4 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/ItemEntity.java
@@ -34,6 +34,7 @@ import org.cloudburstmc.protocol.bedrock.packet.AddItemEntityPacket;
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.ItemTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
@@ -137,7 +138,7 @@ public class ItemEntity extends ThrowableEntity {
protected float getDrag() {
if (isOnGround()) {
Vector3i groundBlockPos = position.toInt().down(1);
- int blockState = session.getGeyser().getWorldManager().getBlockAt(session, groundBlockPos);
+ BlockState blockState = session.getGeyser().getWorldManager().blockAt(session, groundBlockPos);
return BlockStateValues.getSlipperiness(blockState) * 0.98f;
}
return 0.98f;
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java
index 49cfc0081..4d69c8a1e 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java
@@ -28,7 +28,7 @@ package org.geysermc.geyser.entity.type;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
@@ -41,7 +41,7 @@ public class SpawnerMinecartEntity extends DefaultBlockMinecartEntity {
@Override
public void updateDefaultBlockMetadata() {
- dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(BlockStateValues.JAVA_SPAWNER_ID));
+ dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(Blocks.SPAWNER.defaultBlockState()));
dirtyMetadata.put(EntityDataTypes.DISPLAY_OFFSET, 6);
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java
index 3c2160a2b..d7efa9f1d 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java
@@ -33,8 +33,9 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import org.geysermc.geyser.entity.EntityDefinition;
-import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.BlockMapping;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BedBlock;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.VillagerData;
@@ -119,28 +120,31 @@ public class VillagerEntity extends AbstractMerchantEntity {
}
// The bed block
- int blockId = session.getGeyser().getWorldManager().getBlockAt(session, bedPosition);
- String fullIdentifier = BlockRegistries.JAVA_BLOCKS.getOrDefault(blockId, BlockMapping.DEFAULT).getJavaIdentifier();
+ BlockState state = session.getGeyser().getWorldManager().blockAt(session, bedPosition);
// Set the correct position offset and rotation when sleeping
int bedRotation = 0;
float xOffset = 0;
float zOffset = 0;
- if (fullIdentifier.contains("facing=south")) {
- // bed is facing south
- bedRotation = 180;
- zOffset = -.5f;
- } else if (fullIdentifier.contains("facing=east")) {
- // bed is facing east
- bedRotation = 90;
- xOffset = -.5f;
- } else if (fullIdentifier.contains("facing=west")) {
- // bed is facing west
- bedRotation = 270;
- xOffset = .5f;
- } else if (fullIdentifier.contains("facing=north")) {
- // rotation does not change because north is 0
- zOffset = .5f;
+ if (state.block() instanceof BedBlock) {
+ switch (state.getValue(Properties.HORIZONTAL_FACING)) {
+ case SOUTH -> {
+ bedRotation = 180;
+ zOffset = -.5f;
+ }
+ case EAST -> {
+ bedRotation = 90;
+ xOffset = -.5f;
+ }
+ case WEST -> {
+ bedRotation = 270;
+ xOffset = .5f;
+ }
+ case NORTH -> {
+ // rotation does not change because north is 0
+ zOffset = .5f;
+ }
+ }
}
setYaw(yaw);
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
index 533ca3c59..ad6729c42 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java
@@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.DimensionUtils;
@@ -60,16 +61,14 @@ public class SessionPlayerEntity extends PlayerEntity {
*/
@Getter
protected final Map attributes = new Object2ObjectOpenHashMap<>();
- /**
- * Whether to check for updated speed after all entity metadata has been processed
- */
- private boolean refreshSpeed = false;
/**
* Used in PlayerInputTranslator for movement checks.
*/
@Getter
private boolean isRidingInFront;
+ private int lastAirSupply = getMaxAir();
+
public SessionPlayerEntity(GeyserSession session) {
super(session, -1, 1, null, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, null, null);
@@ -120,9 +119,7 @@ public class SessionPlayerEntity extends PlayerEntity {
// TODO: proper fix, BDS somehow does it? https://paste.gg/p/anonymous/3adfb7612f1540be80fa03a2281f93dc (BDS 1.20.13)
if (!this.session.getGameMode().equals(GameMode.SPECTATOR)) {
super.setFlags(entityMetadata);
- session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING));
}
- refreshSpeed = true;
}
/**
@@ -150,7 +147,6 @@ public class SessionPlayerEntity extends PlayerEntity {
public void setPose(Pose pose) {
super.setPose(pose);
session.setPose(pose);
- refreshSpeed = true;
}
public float getMaxHealth() {
@@ -167,7 +163,13 @@ public class SessionPlayerEntity extends PlayerEntity {
@Override
protected void setAirSupply(int amount) {
- if (amount == getMaxAir()) {
+ // Seemingly required to be sent as of Bedrock 1.21. Otherwise, bubbles will appear as empty
+ // Also, this changes how the air bubble graphics/sounds are presented. Breathing on means sound effects and
+ // the bubbles visually pop
+ setFlag(EntityFlag.BREATHING, amount >= this.lastAirSupply);
+ this.lastAirSupply = amount;
+
+ if (amount == getMaxAir() && GameProtocol.isPre1_21_0(session)) {
super.setAirSupply(0); // Hide the bubble counter from the UI for the player
} else {
super.setAirSupply(amount);
@@ -199,21 +201,6 @@ public class SessionPlayerEntity extends PlayerEntity {
}
}
- @Override
- public void updateBedrockMetadata() {
- super.updateBedrockMetadata();
- if (refreshSpeed) {
- AttributeData speedAttribute = session.adjustSpeed();
- if (speedAttribute != null) {
- UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
- attributesPacket.setRuntimeEntityId(geyserId);
- attributesPacket.setAttributes(Collections.singletonList(speedAttribute));
- session.sendUpstreamPacket(attributesPacket);
- }
- refreshSpeed = false;
- }
- }
-
@Override
protected void updateAttribute(Attribute javaAttribute, List newAttributes) {
if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_ATTACK_SPEED) {
@@ -226,17 +213,6 @@ public class SessionPlayerEntity extends PlayerEntity {
@Override
protected AttributeData calculateAttribute(Attribute javaAttribute, GeyserAttributeType type) {
AttributeData attributeData = super.calculateAttribute(javaAttribute, type);
-
- if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_MOVEMENT_SPEED) {
- session.setOriginalSpeedAttribute(attributeData.getValue());
- AttributeData speedAttribute = session.adjustSpeed();
- if (speedAttribute != null) {
- // Overwrite the attribute with our own
- this.attributes.put(type, speedAttribute);
- return speedAttribute;
- }
- }
-
this.attributes.put(type, attributeData);
return attributeData;
}
diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java
index 89f9c37d6..f2f93b266 100644
--- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SkullPlayerEntity.java
@@ -34,7 +34,10 @@ import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.block.type.WallSkullBlock;
+import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.SkullCache;
import org.geysermc.geyser.skin.SkullSkinManager;
@@ -137,20 +140,19 @@ public class SkullPlayerEntity extends PlayerEntity {
float z = skull.getPosition().getZ() + .5f;
float rotation;
- int blockState = skull.getBlockState();
- byte floorRotation = BlockStateValues.getSkullRotation(blockState);
- if (floorRotation == -1) {
- // Wall skull
+ BlockState blockState = skull.getBlockState();
+ if (blockState.block() instanceof WallSkullBlock) {
y += 0.25f;
- rotation = BlockStateValues.getSkullWallDirections().get(blockState);
- switch ((int) rotation) {
- case 180 -> z += 0.24f; // North
- case 0 -> z -= 0.24f; // South
- case 90 -> x += 0.24f; // West
- case 270 -> x -= 0.24f; // East
+ Direction direction = blockState.getValue(Properties.HORIZONTAL_FACING);
+ rotation = WallSkullBlock.getDegrees(direction);
+ switch (direction) {
+ case NORTH -> z += 0.24f;
+ case SOUTH -> z -= 0.24f;
+ case WEST -> x += 0.24f;
+ case EAST -> x -= 0.24f;
}
} else {
- rotation = (180f + (floorRotation * 22.5f)) % 360;
+ rotation = (180f + (blockState.getValue(Properties.ROTATION_16) * 22.5f)) % 360;
}
moveAbsolute(Vector3f.from(x, y, z), rotation, 0, rotation, true, true);
diff --git a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java
index a62f9ec49..c8cbe384b 100644
--- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java
+++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java
@@ -25,14 +25,13 @@
package org.geysermc.geyser.erosion;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
import io.netty.channel.Channel;
+import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import lombok.Getter;
import lombok.Setter;
import org.cloudburstmc.math.vector.Vector3i;
@@ -43,21 +42,18 @@ import org.geysermc.erosion.packet.ErosionPacketHandler;
import org.geysermc.erosion.packet.ErosionPacketSender;
import org.geysermc.erosion.packet.backendbound.BackendboundInitializePacket;
import org.geysermc.erosion.packet.backendbound.BackendboundPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundBatchBlockIdPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockEntityPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockIdPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockLookupFailPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockPlacePacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundHandshakePacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundPickBlockPacket;
-import org.geysermc.erosion.packet.geyserbound.GeyserboundPistonEventPacket;
+import org.geysermc.erosion.packet.geyserbound.*;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.PistonCache;
import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity;
import org.geysermc.geyser.util.BlockEntityUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
@@ -71,7 +67,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
@Setter
private CompletableFuture pendingBatchLookup = null;
@Setter
- private CompletableFuture pickBlockLookup = null;
+ private CompletableFuture> pickBlockLookup = null;
private final AtomicInteger nextTransactionId = new AtomicInteger(1);
@@ -127,7 +123,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
}
CompletableFuture future = this.asyncPendingLookups.remove(transactionId);
if (future != null) {
- future.complete(BlockStateValues.JAVA_AIR_ID);
+ future.complete(Block.JAVA_AIR_ID);
}
}
@@ -141,28 +137,29 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
placeBlockSoundPacket.setIdentifier(":");
session.sendUpstreamPacket(placeBlockSoundPacket);
session.setLastBlockPlacePosition(null);
- session.setLastBlockPlacedId(null);
+ session.setLastBlockPlaced(null);
}
@Override
public void handlePickBlock(GeyserboundPickBlockPacket packet) {
if (this.pickBlockLookup != null) {
- //this.pickBlockLookup.complete(packet.getTag()); // TODO 1.20.5
+ this.pickBlockLookup.complete(packet.getComponents());
}
}
@Override
public void handlePistonEvent(GeyserboundPistonEventPacket packet) {
- Direction orientation = BlockStateValues.getPistonOrientation(packet.getBlockId());
+ Direction orientation = BlockState.of(packet.getBlockId()).getValue(Properties.FACING);
Vector3i position = packet.getPos();
boolean isExtend = packet.isExtend();
var stream = packet.getAttachedBlocks()
.object2IntEntrySet()
.stream()
- .filter(entry -> BlockStateValues.canPistonMoveBlock(entry.getIntValue(), isExtend));
- Object2IntMap attachedBlocks = new Object2IntArrayMap<>();
- stream.forEach(entry -> attachedBlocks.put(entry.getKey(), entry.getIntValue()));
+ .map(entry -> Pair.of(entry.getKey(), BlockState.of(entry.getIntValue())))
+ .filter(pair -> BlockStateValues.canPistonMoveBlock(pair.value(), isExtend));
+ Object2ObjectMap attachedBlocks = new Object2ObjectArrayMap<>();
+ stream.forEach(pair -> attachedBlocks.put(pair.key(), pair.value()));
session.executeInEventLoop(() -> {
PistonCache pistonCache = session.getPistonCache();
diff --git a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java
index 2a93c89e3..7582502b3 100644
--- a/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java
+++ b/core/src/main/java/org/geysermc/geyser/impl/camera/GeyserCameraData.java
@@ -32,24 +32,50 @@ import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.CameraShakeAction;
import org.cloudburstmc.protocol.bedrock.data.CameraShakeType;
+import org.cloudburstmc.protocol.bedrock.data.HudElement;
+import org.cloudburstmc.protocol.bedrock.data.HudVisibility;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraEase;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraFadeInstruction;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraSetInstruction;
import org.cloudburstmc.protocol.bedrock.packet.CameraInstructionPacket;
import org.cloudburstmc.protocol.bedrock.packet.CameraShakePacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerFogPacket;
-import org.geysermc.geyser.api.bedrock.camera.*;
+import org.cloudburstmc.protocol.bedrock.packet.SetHudPacket;
+import org.geysermc.geyser.api.bedrock.camera.CameraData;
+import org.geysermc.geyser.api.bedrock.camera.CameraEaseType;
+import org.geysermc.geyser.api.bedrock.camera.CameraFade;
+import org.geysermc.geyser.api.bedrock.camera.CameraPerspective;
+import org.geysermc.geyser.api.bedrock.camera.CameraPosition;
+import org.geysermc.geyser.api.bedrock.camera.CameraShake;
+import org.geysermc.geyser.api.bedrock.camera.GuiElement;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
-import java.util.*;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
public class GeyserCameraData implements CameraData {
+ private static final HudElement[] HUD_ELEMENT_VALUES = HudElement.values();
+ private static final Set ALL_HUD_ELEMENTS = Set.of(HUD_ELEMENT_VALUES);
+
+ /**
+ * An array of elements to hide when the player is in spectator mode.
+ * Helps with tidying up the GUI; Java-style.
+ */
+ private static final GuiElement[] SPECTATOR_HIDDEN_ELEMENTS = {
+ GuiElement.AIR_BUBBLES_BAR,
+ GuiElement.ARMOR,
+ GuiElement.HEALTH,
+ GuiElement.FOOD_BAR,
+ GuiElement.PROGRESS_BAR,
+ GuiElement.TOOL_TIPS
+ };
private final GeyserSession session;
- @Getter
- private CameraPerspective cameraPerspective;
-
/**
* All fog effects that are currently applied to the client.
*/
@@ -57,6 +83,14 @@ public class GeyserCameraData implements CameraData {
private final Set cameraLockOwners = new HashSet<>();
+ /**
+ * All currently hidden HUD elements
+ */
+ private final Set hiddenHudElements = new HashSet<>();
+
+ @Getter
+ private CameraPerspective cameraPerspective;
+
public GeyserCameraData(GeyserSession session) {
this.session = session;
}
@@ -223,4 +257,67 @@ public class GeyserCameraData implements CameraData {
public boolean isCameraLocked() {
return !this.cameraLockOwners.isEmpty();
}
-}
\ No newline at end of file
+
+ @Override
+ public void hideElement(GuiElement... elements) {
+ Objects.requireNonNull(elements);
+ SetHudPacket packet = new SetHudPacket();
+ packet.setVisibility(HudVisibility.HIDE);
+ Set elementSet = packet.getElements();
+
+ for (GuiElement element : elements) {
+ this.hiddenHudElements.add(element);
+ elementSet.add(HUD_ELEMENT_VALUES[element.id()]);
+ }
+
+ session.sendUpstreamPacket(packet);
+ }
+
+ @Override
+ public void resetElement(GuiElement... elements) {
+ SetHudPacket packet = new SetHudPacket();
+ packet.setVisibility(HudVisibility.RESET);
+ Set elementSet = packet.getElements();
+
+ if (elements != null && elements.length != 0) {
+ for (GuiElement element : elements) {
+ this.hiddenHudElements.remove(element);
+ elementSet.add(HUD_ELEMENT_VALUES[element.id()]);
+ }
+ } else {
+ this.hiddenHudElements.clear();
+ elementSet.addAll(ALL_HUD_ELEMENTS);
+ }
+
+ session.sendUpstreamPacket(packet);
+ }
+
+ @Override
+ public boolean isHudElementHidden(@NonNull GuiElement element) {
+ Objects.requireNonNull(element);
+ return this.hiddenHudElements.contains(element);
+ }
+
+ @Override
+ public @NonNull Set hiddenElements() {
+ return Collections.unmodifiableSet(hiddenHudElements);
+ }
+
+ /**
+ * Deals with hiding hud elements while in spectator.
+ *
+ * @param currentlySpectator whether the player is currently in spectator mode
+ * @param newGameMode the new GameMode to switch to
+ */
+ public void handleGameModeChange(boolean currentlySpectator, GameMode newGameMode) {
+ if (newGameMode == GameMode.SPECTATOR) {
+ if (!currentlySpectator) {
+ hideElement(SPECTATOR_HIDDEN_ELEMENTS);
+ }
+ } else {
+ if (currentlySpectator) {
+ resetElement(SPECTATOR_HIDDEN_ELEMENTS);
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Container.java b/core/src/main/java/org/geysermc/geyser/inventory/Container.java
index 209aeb24f..81818613f 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/Container.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/Container.java
@@ -25,6 +25,7 @@
package org.geysermc.geyser.inventory;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -83,9 +84,9 @@ public class Container extends Inventory {
* Will be overwritten for droppers.
*
* @param usingRealBlock whether this container is using a real container or not
- * @param javaBlockId the Java block string of the block, if real
+ * @param block the Java block, if real
*/
- public void setUsingRealBlock(boolean usingRealBlock, String javaBlockId) {
+ public void setUsingRealBlock(boolean usingRealBlock, Block block) {
isUsingRealBlock = usingRealBlock;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java b/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java
index 65e47d877..0b14d1105 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java
@@ -26,6 +26,8 @@
package org.geysermc.geyser.inventory;
import lombok.Getter;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.Generic3X3InventoryTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
@@ -44,10 +46,10 @@ public class Generic3X3Container extends Container {
}
@Override
- public void setUsingRealBlock(boolean usingRealBlock, String javaBlockId) {
- super.setUsingRealBlock(usingRealBlock, javaBlockId);
+ public void setUsingRealBlock(boolean usingRealBlock, Block block) {
+ super.setUsingRealBlock(usingRealBlock, block);
if (usingRealBlock) {
- isDropper = javaBlockId.startsWith("minecraft:dropper");
+ isDropper = block == Blocks.DROPPER;
}
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java
index fa62769fe..744ad70b6 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java
@@ -69,7 +69,7 @@ public class GeyserItemStack {
return of(javaId, amount, null);
}
- public static @NonNull GeyserItemStack of(int javaId, int amount, DataComponents components) {
+ public static @NonNull GeyserItemStack of(int javaId, int amount, @Nullable DataComponents components) {
return new GeyserItemStack(javaId, amount, components);
}
diff --git a/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java
index c11505ffb..cdda4fe4c 100644
--- a/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java
+++ b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java
@@ -36,11 +36,11 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.Container;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.LecternContainer;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
-import org.geysermc.geyser.util.BlockUtils;
import org.geysermc.geyser.util.InventoryUtils;
import java.util.Collections;
@@ -55,20 +55,24 @@ public class BlockInventoryHolder extends InventoryHolder {
/**
* The default Java block ID to translate as a fake block
*/
- private final int defaultJavaBlockState;
+ private final BlockState defaultJavaBlockState;
private final ContainerType containerType;
- private final Set validBlocks;
+ private final Set validBlocks;
- public BlockInventoryHolder(String javaBlockIdentifier, ContainerType containerType, String... validBlocks) {
- this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt(javaBlockIdentifier);
+ public BlockInventoryHolder(Block defaultJavaBlock, ContainerType containerType, Block... validBlocks) {
+ this(defaultJavaBlock.defaultBlockState(), containerType, validBlocks);
+ }
+
+ public BlockInventoryHolder(BlockState defaultJavaBlockState, ContainerType containerType, Block... validBlocks) {
+ this.defaultJavaBlockState = defaultJavaBlockState;
this.containerType = containerType;
if (validBlocks != null) {
- Set validBlocksTemp = new HashSet<>(validBlocks.length + 1);
+ Set validBlocksTemp = new HashSet<>(validBlocks.length + 1);
Collections.addAll(validBlocksTemp, validBlocks);
- validBlocksTemp.add(BlockUtils.getCleanIdentifier(javaBlockIdentifier));
+ validBlocksTemp.add(defaultJavaBlockState.block());
this.validBlocks = Set.copyOf(validBlocksTemp);
} else {
- this.validBlocks = Collections.singleton(BlockUtils.getCleanIdentifier(javaBlockIdentifier));
+ this.validBlocks = Collections.singleton(defaultJavaBlockState.block());
}
}
@@ -80,14 +84,13 @@ public class BlockInventoryHolder extends InventoryHolder {
if (checkInteractionPosition(session)) {
// Then, check to see if the interacted block is valid for this inventory by ensuring the block state identifier is valid
// and the bedrock block is vanilla
- int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition());
- if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(javaBlockId)) {
- String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.DEFAULT).getJavaIdentifier().split("\\[");
- if (isValidBlock(javaBlockString)) {
+ BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getLastInteractionBlockPosition());
+ if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(state.javaId())) {
+ if (isValidBlock(state)) {
// We can safely use this block
inventory.setHolderPosition(session.getLastInteractionBlockPosition());
- ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]);
- setCustomName(session, session.getLastInteractionBlockPosition(), inventory, javaBlockId);
+ ((Container) inventory).setUsingRealBlock(true, state.block());
+ setCustomName(session, session.getLastInteractionBlockPosition(), inventory, state);
return true;
}
@@ -125,11 +128,11 @@ public class BlockInventoryHolder extends InventoryHolder {
/**
* @return true if this Java block ID can be used for player inventory.
*/
- protected boolean isValidBlock(String[] javaBlockString) {
- return this.validBlocks.contains(javaBlockString[0]);
+ protected boolean isValidBlock(BlockState blockState) {
+ return this.validBlocks.contains(blockState.block());
}
- protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, int javaBlockState) {
+ protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, BlockState javaBlockState) {
NbtMap tag = NbtMap.builder()
.putInt("x", position.getX())
.putInt("y", position.getY())
@@ -160,6 +163,7 @@ public class BlockInventoryHolder extends InventoryHolder {
ContainerClosePacket packet = new ContainerClosePacket();
packet.setId((byte) inventory.getBedrockId());
packet.setServerInitiated(true);
+ packet.setType(ContainerType.CONTAINER);
session.sendUpstreamPacket(packet);
return;
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java
index f13330700..03f044068 100644
--- a/core/src/main/java/org/geysermc/geyser/item/Items.java
+++ b/core/src/main/java/org/geysermc/geyser/item/Items.java
@@ -27,10 +27,9 @@ package org.geysermc.geyser.item;
import org.geysermc.geyser.item.components.ToolTier;
import org.geysermc.geyser.item.type.*;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.registry.Registries;
-import java.util.Collections;
-
import static org.geysermc.geyser.item.type.Item.builder;
/**
@@ -39,770 +38,770 @@ import static org.geysermc.geyser.item.type.Item.builder;
@SuppressWarnings("unused")
public final class Items {
public static final Item AIR = register(new Item("air", builder()));
- public static final Item STONE = register(new BlockItem("stone", builder()));
- public static final Item GRANITE = register(new BlockItem("granite", builder()));
- public static final Item POLISHED_GRANITE = register(new BlockItem("polished_granite", builder()));
- public static final Item DIORITE = register(new BlockItem("diorite", builder()));
- public static final Item POLISHED_DIORITE = register(new BlockItem("polished_diorite", builder()));
- public static final Item ANDESITE = register(new BlockItem("andesite", builder()));
- public static final Item POLISHED_ANDESITE = register(new BlockItem("polished_andesite", builder()));
- public static final Item DEEPSLATE = register(new BlockItem("deepslate", builder()));
- public static final Item COBBLED_DEEPSLATE = register(new BlockItem("cobbled_deepslate", builder()));
- public static final Item POLISHED_DEEPSLATE = register(new BlockItem("polished_deepslate", builder()));
- public static final Item CALCITE = register(new BlockItem("calcite", builder()));
- public static final Item TUFF = register(new BlockItem("tuff", builder()));
- public static final Item TUFF_SLAB = register(new BlockItem("tuff_slab", builder()));
- public static final Item TUFF_STAIRS = register(new BlockItem("tuff_stairs", builder()));
- public static final Item TUFF_WALL = register(new BlockItem("tuff_wall", builder()));
- public static final Item CHISELED_TUFF = register(new BlockItem("chiseled_tuff", builder()));
- public static final Item POLISHED_TUFF = register(new BlockItem("polished_tuff", builder()));
- public static final Item POLISHED_TUFF_SLAB = register(new BlockItem("polished_tuff_slab", builder()));
- public static final Item POLISHED_TUFF_STAIRS = register(new BlockItem("polished_tuff_stairs", builder()));
- public static final Item POLISHED_TUFF_WALL = register(new BlockItem("polished_tuff_wall", builder()));
- public static final Item TUFF_BRICKS = register(new BlockItem("tuff_bricks", builder()));
- public static final Item TUFF_BRICK_SLAB = register(new BlockItem("tuff_brick_slab", builder()));
- public static final Item TUFF_BRICK_STAIRS = register(new BlockItem("tuff_brick_stairs", builder()));
- public static final Item TUFF_BRICK_WALL = register(new BlockItem("tuff_brick_wall", builder()));
- public static final Item CHISELED_TUFF_BRICKS = register(new BlockItem("chiseled_tuff_bricks", builder()));
- public static final Item DRIPSTONE_BLOCK = register(new BlockItem("dripstone_block", builder()));
- public static final Item GRASS_BLOCK = register(new BlockItem("grass_block", builder()));
- public static final Item DIRT = register(new BlockItem("dirt", builder()));
- public static final Item COARSE_DIRT = register(new BlockItem("coarse_dirt", builder()));
- public static final Item PODZOL = register(new BlockItem("podzol", builder()));
- public static final Item ROOTED_DIRT = register(new BlockItem("rooted_dirt", builder()));
- public static final Item MUD = register(new BlockItem("mud", builder()));
- public static final Item CRIMSON_NYLIUM = register(new BlockItem("crimson_nylium", builder()));
- public static final Item WARPED_NYLIUM = register(new BlockItem("warped_nylium", builder()));
- public static final Item COBBLESTONE = register(new BlockItem("cobblestone", builder()));
- public static final Item OAK_PLANKS = register(new BlockItem("oak_planks", builder()));
- public static final Item SPRUCE_PLANKS = register(new BlockItem("spruce_planks", builder()));
- public static final Item BIRCH_PLANKS = register(new BlockItem("birch_planks", builder()));
- public static final Item JUNGLE_PLANKS = register(new BlockItem("jungle_planks", builder()));
- public static final Item ACACIA_PLANKS = register(new BlockItem("acacia_planks", builder()));
- public static final Item CHERRY_PLANKS = register(new BlockItem("cherry_planks", builder()));
- public static final Item DARK_OAK_PLANKS = register(new BlockItem("dark_oak_planks", builder()));
- public static final Item MANGROVE_PLANKS = register(new BlockItem("mangrove_planks", builder()));
- public static final Item BAMBOO_PLANKS = register(new BlockItem("bamboo_planks", builder()));
- public static final Item CRIMSON_PLANKS = register(new BlockItem("crimson_planks", builder()));
- public static final Item WARPED_PLANKS = register(new BlockItem("warped_planks", builder()));
- public static final Item BAMBOO_MOSAIC = register(new BlockItem("bamboo_mosaic", builder()));
- public static final Item OAK_SAPLING = register(new BlockItem("oak_sapling", builder()));
- public static final Item SPRUCE_SAPLING = register(new BlockItem("spruce_sapling", builder()));
- public static final Item BIRCH_SAPLING = register(new BlockItem("birch_sapling", builder()));
- public static final Item JUNGLE_SAPLING = register(new BlockItem("jungle_sapling", builder()));
- public static final Item ACACIA_SAPLING = register(new BlockItem("acacia_sapling", builder()));
- public static final Item CHERRY_SAPLING = register(new BlockItem("cherry_sapling", builder()));
- public static final Item DARK_OAK_SAPLING = register(new BlockItem("dark_oak_sapling", builder()));
- public static final Item MANGROVE_PROPAGULE = register(new BlockItem("mangrove_propagule", builder()));
- public static final Item BEDROCK = register(new BlockItem("bedrock", builder()));
- public static final Item SAND = register(new BlockItem("sand", builder()));
- public static final Item SUSPICIOUS_SAND = register(new BlockItem("suspicious_sand", builder()));
- public static final Item SUSPICIOUS_GRAVEL = register(new BlockItem("suspicious_gravel", builder()));
- public static final Item RED_SAND = register(new BlockItem("red_sand", builder()));
- public static final Item GRAVEL = register(new BlockItem("gravel", builder()));
- public static final Item COAL_ORE = register(new BlockItem("coal_ore", builder()));
- public static final Item DEEPSLATE_COAL_ORE = register(new BlockItem("deepslate_coal_ore", builder()));
- public static final Item IRON_ORE = register(new BlockItem("iron_ore", builder()));
- public static final Item DEEPSLATE_IRON_ORE = register(new BlockItem("deepslate_iron_ore", builder()));
- public static final Item COPPER_ORE = register(new BlockItem("copper_ore", builder()));
- public static final Item DEEPSLATE_COPPER_ORE = register(new BlockItem("deepslate_copper_ore", builder()));
- public static final Item GOLD_ORE = register(new BlockItem("gold_ore", builder()));
- public static final Item DEEPSLATE_GOLD_ORE = register(new BlockItem("deepslate_gold_ore", builder()));
- public static final Item REDSTONE_ORE = register(new BlockItem("redstone_ore", builder()));
- public static final Item DEEPSLATE_REDSTONE_ORE = register(new BlockItem("deepslate_redstone_ore", builder()));
- public static final Item EMERALD_ORE = register(new BlockItem("emerald_ore", builder()));
- public static final Item DEEPSLATE_EMERALD_ORE = register(new BlockItem("deepslate_emerald_ore", builder()));
- public static final Item LAPIS_ORE = register(new BlockItem("lapis_ore", builder()));
- public static final Item DEEPSLATE_LAPIS_ORE = register(new BlockItem("deepslate_lapis_ore", builder()));
- public static final Item DIAMOND_ORE = register(new BlockItem("diamond_ore", builder()));
- public static final Item DEEPSLATE_DIAMOND_ORE = register(new BlockItem("deepslate_diamond_ore", builder()));
- public static final Item NETHER_GOLD_ORE = register(new BlockItem("nether_gold_ore", builder()));
- public static final Item NETHER_QUARTZ_ORE = register(new BlockItem("nether_quartz_ore", builder()));
- public static final Item ANCIENT_DEBRIS = register(new BlockItem("ancient_debris", builder()));
- public static final Item COAL_BLOCK = register(new BlockItem("coal_block", builder()));
- public static final Item RAW_IRON_BLOCK = register(new BlockItem("raw_iron_block", builder()));
- public static final Item RAW_COPPER_BLOCK = register(new BlockItem("raw_copper_block", builder()));
- public static final Item RAW_GOLD_BLOCK = register(new BlockItem("raw_gold_block", builder()));
- public static final Item HEAVY_CORE = register(new BlockItem("heavy_core", builder()));
- public static final Item AMETHYST_BLOCK = register(new BlockItem("amethyst_block", builder()));
- public static final Item BUDDING_AMETHYST = register(new BlockItem("budding_amethyst", builder()));
- public static final Item IRON_BLOCK = register(new BlockItem("iron_block", builder()));
- public static final Item COPPER_BLOCK = register(new BlockItem("copper_block", builder()));
- public static final Item GOLD_BLOCK = register(new BlockItem("gold_block", builder()));
- public static final Item DIAMOND_BLOCK = register(new BlockItem("diamond_block", builder()));
- public static final Item NETHERITE_BLOCK = register(new BlockItem("netherite_block", builder()));
- public static final Item EXPOSED_COPPER = register(new BlockItem("exposed_copper", builder()));
- public static final Item WEATHERED_COPPER = register(new BlockItem("weathered_copper", builder()));
- public static final Item OXIDIZED_COPPER = register(new BlockItem("oxidized_copper", builder()));
- public static final Item CHISELED_COPPER = register(new BlockItem("chiseled_copper", builder()));
- public static final Item EXPOSED_CHISELED_COPPER = register(new BlockItem("exposed_chiseled_copper", builder()));
- public static final Item WEATHERED_CHISELED_COPPER = register(new BlockItem("weathered_chiseled_copper", builder()));
- public static final Item OXIDIZED_CHISELED_COPPER = register(new BlockItem("oxidized_chiseled_copper", builder()));
- public static final Item CUT_COPPER = register(new BlockItem("cut_copper", builder()));
- public static final Item EXPOSED_CUT_COPPER = register(new BlockItem("exposed_cut_copper", builder()));
- public static final Item WEATHERED_CUT_COPPER = register(new BlockItem("weathered_cut_copper", builder()));
- public static final Item OXIDIZED_CUT_COPPER = register(new BlockItem("oxidized_cut_copper", builder()));
- public static final Item CUT_COPPER_STAIRS = register(new BlockItem("cut_copper_stairs", builder()));
- public static final Item EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem("exposed_cut_copper_stairs", builder()));
- public static final Item WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem("weathered_cut_copper_stairs", builder()));
- public static final Item OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem("oxidized_cut_copper_stairs", builder()));
- public static final Item CUT_COPPER_SLAB = register(new BlockItem("cut_copper_slab", builder()));
- public static final Item EXPOSED_CUT_COPPER_SLAB = register(new BlockItem("exposed_cut_copper_slab", builder()));
- public static final Item WEATHERED_CUT_COPPER_SLAB = register(new BlockItem("weathered_cut_copper_slab", builder()));
- public static final Item OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem("oxidized_cut_copper_slab", builder()));
- public static final Item WAXED_COPPER_BLOCK = register(new BlockItem("waxed_copper_block", builder()));
- public static final Item WAXED_EXPOSED_COPPER = register(new BlockItem("waxed_exposed_copper", builder()));
- public static final Item WAXED_WEATHERED_COPPER = register(new BlockItem("waxed_weathered_copper", builder()));
- public static final Item WAXED_OXIDIZED_COPPER = register(new BlockItem("waxed_oxidized_copper", builder()));
- public static final Item WAXED_CHISELED_COPPER = register(new BlockItem("waxed_chiseled_copper", builder()));
- public static final Item WAXED_EXPOSED_CHISELED_COPPER = register(new BlockItem("waxed_exposed_chiseled_copper", builder()));
- public static final Item WAXED_WEATHERED_CHISELED_COPPER = register(new BlockItem("waxed_weathered_chiseled_copper", builder()));
- public static final Item WAXED_OXIDIZED_CHISELED_COPPER = register(new BlockItem("waxed_oxidized_chiseled_copper", builder()));
- public static final Item WAXED_CUT_COPPER = register(new BlockItem("waxed_cut_copper", builder()));
- public static final Item WAXED_EXPOSED_CUT_COPPER = register(new BlockItem("waxed_exposed_cut_copper", builder()));
- public static final Item WAXED_WEATHERED_CUT_COPPER = register(new BlockItem("waxed_weathered_cut_copper", builder()));
- public static final Item WAXED_OXIDIZED_CUT_COPPER = register(new BlockItem("waxed_oxidized_cut_copper", builder()));
- public static final Item WAXED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_cut_copper_stairs", builder()));
- public static final Item WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_exposed_cut_copper_stairs", builder()));
- public static final Item WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_weathered_cut_copper_stairs", builder()));
- public static final Item WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_oxidized_cut_copper_stairs", builder()));
- public static final Item WAXED_CUT_COPPER_SLAB = register(new BlockItem("waxed_cut_copper_slab", builder()));
- public static final Item WAXED_EXPOSED_CUT_COPPER_SLAB = register(new BlockItem("waxed_exposed_cut_copper_slab", builder()));
- public static final Item WAXED_WEATHERED_CUT_COPPER_SLAB = register(new BlockItem("waxed_weathered_cut_copper_slab", builder()));
- public static final Item WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem("waxed_oxidized_cut_copper_slab", builder()));
- public static final Item OAK_LOG = register(new BlockItem("oak_log", builder()));
- public static final Item SPRUCE_LOG = register(new BlockItem("spruce_log", builder()));
- public static final Item BIRCH_LOG = register(new BlockItem("birch_log", builder()));
- public static final Item JUNGLE_LOG = register(new BlockItem("jungle_log", builder()));
- public static final Item ACACIA_LOG = register(new BlockItem("acacia_log", builder()));
- public static final Item CHERRY_LOG = register(new BlockItem("cherry_log", builder()));
- public static final Item DARK_OAK_LOG = register(new BlockItem("dark_oak_log", builder()));
- public static final Item MANGROVE_LOG = register(new BlockItem("mangrove_log", builder()));
- public static final Item MANGROVE_ROOTS = register(new BlockItem("mangrove_roots", builder()));
- public static final Item MUDDY_MANGROVE_ROOTS = register(new BlockItem("muddy_mangrove_roots", builder()));
- public static final Item CRIMSON_STEM = register(new BlockItem("crimson_stem", builder()));
- public static final Item WARPED_STEM = register(new BlockItem("warped_stem", builder()));
- public static final Item BAMBOO_BLOCK = register(new BlockItem("bamboo_block", builder()));
- public static final Item STRIPPED_OAK_LOG = register(new BlockItem("stripped_oak_log", builder()));
- public static final Item STRIPPED_SPRUCE_LOG = register(new BlockItem("stripped_spruce_log", builder()));
- public static final Item STRIPPED_BIRCH_LOG = register(new BlockItem("stripped_birch_log", builder()));
- public static final Item STRIPPED_JUNGLE_LOG = register(new BlockItem("stripped_jungle_log", builder()));
- public static final Item STRIPPED_ACACIA_LOG = register(new BlockItem("stripped_acacia_log", builder()));
- public static final Item STRIPPED_CHERRY_LOG = register(new BlockItem("stripped_cherry_log", builder()));
- public static final Item STRIPPED_DARK_OAK_LOG = register(new BlockItem("stripped_dark_oak_log", builder()));
- public static final Item STRIPPED_MANGROVE_LOG = register(new BlockItem("stripped_mangrove_log", builder()));
- public static final Item STRIPPED_CRIMSON_STEM = register(new BlockItem("stripped_crimson_stem", builder()));
- public static final Item STRIPPED_WARPED_STEM = register(new BlockItem("stripped_warped_stem", builder()));
- public static final Item STRIPPED_OAK_WOOD = register(new BlockItem("stripped_oak_wood", builder()));
- public static final Item STRIPPED_SPRUCE_WOOD = register(new BlockItem("stripped_spruce_wood", builder()));
- public static final Item STRIPPED_BIRCH_WOOD = register(new BlockItem("stripped_birch_wood", builder()));
- public static final Item STRIPPED_JUNGLE_WOOD = register(new BlockItem("stripped_jungle_wood", builder()));
- public static final Item STRIPPED_ACACIA_WOOD = register(new BlockItem("stripped_acacia_wood", builder()));
- public static final Item STRIPPED_CHERRY_WOOD = register(new BlockItem("stripped_cherry_wood", builder()));
- public static final Item STRIPPED_DARK_OAK_WOOD = register(new BlockItem("stripped_dark_oak_wood", builder()));
- public static final Item STRIPPED_MANGROVE_WOOD = register(new BlockItem("stripped_mangrove_wood", builder()));
- public static final Item STRIPPED_CRIMSON_HYPHAE = register(new BlockItem("stripped_crimson_hyphae", builder()));
- public static final Item STRIPPED_WARPED_HYPHAE = register(new BlockItem("stripped_warped_hyphae", builder()));
- public static final Item STRIPPED_BAMBOO_BLOCK = register(new BlockItem("stripped_bamboo_block", builder()));
- public static final Item OAK_WOOD = register(new BlockItem("oak_wood", builder()));
- public static final Item SPRUCE_WOOD = register(new BlockItem("spruce_wood", builder()));
- public static final Item BIRCH_WOOD = register(new BlockItem("birch_wood", builder()));
- public static final Item JUNGLE_WOOD = register(new BlockItem("jungle_wood", builder()));
- public static final Item ACACIA_WOOD = register(new BlockItem("acacia_wood", builder()));
- public static final Item CHERRY_WOOD = register(new BlockItem("cherry_wood", builder()));
- public static final Item DARK_OAK_WOOD = register(new BlockItem("dark_oak_wood", builder()));
- public static final Item MANGROVE_WOOD = register(new BlockItem("mangrove_wood", builder()));
- public static final Item CRIMSON_HYPHAE = register(new BlockItem("crimson_hyphae", builder()));
- public static final Item WARPED_HYPHAE = register(new BlockItem("warped_hyphae", builder()));
- public static final Item OAK_LEAVES = register(new BlockItem("oak_leaves", builder()));
- public static final Item SPRUCE_LEAVES = register(new BlockItem("spruce_leaves", builder()));
- public static final Item BIRCH_LEAVES = register(new BlockItem("birch_leaves", builder()));
- public static final Item JUNGLE_LEAVES = register(new BlockItem("jungle_leaves", builder()));
- public static final Item ACACIA_LEAVES = register(new BlockItem("acacia_leaves", builder()));
- public static final Item CHERRY_LEAVES = register(new BlockItem("cherry_leaves", builder()));
- public static final Item DARK_OAK_LEAVES = register(new BlockItem("dark_oak_leaves", builder()));
- public static final Item MANGROVE_LEAVES = register(new BlockItem("mangrove_leaves", builder()));
- public static final Item AZALEA_LEAVES = register(new BlockItem("azalea_leaves", builder()));
- public static final Item FLOWERING_AZALEA_LEAVES = register(new BlockItem("flowering_azalea_leaves", builder()));
- public static final Item SPONGE = register(new BlockItem("sponge", builder()));
- public static final Item WET_SPONGE = register(new BlockItem("wet_sponge", builder()));
- public static final Item GLASS = register(new BlockItem("glass", builder()));
- public static final Item TINTED_GLASS = register(new BlockItem("tinted_glass", builder()));
- public static final Item LAPIS_BLOCK = register(new BlockItem("lapis_block", builder()));
- public static final Item SANDSTONE = register(new BlockItem("sandstone", builder()));
- public static final Item CHISELED_SANDSTONE = register(new BlockItem("chiseled_sandstone", builder()));
- public static final Item CUT_SANDSTONE = register(new BlockItem("cut_sandstone", builder()));
- public static final Item COBWEB = register(new BlockItem("cobweb", builder()));
- public static final Item SHORT_GRASS = register(new BlockItem("short_grass", builder()));
- public static final Item FERN = register(new BlockItem("fern", builder()));
- public static final Item AZALEA = register(new BlockItem("azalea", builder()));
- public static final Item FLOWERING_AZALEA = register(new BlockItem("flowering_azalea", builder()));
- public static final Item DEAD_BUSH = register(new BlockItem("dead_bush", builder()));
- public static final Item SEAGRASS = register(new BlockItem("seagrass", builder()));
- public static final Item SEA_PICKLE = register(new BlockItem("sea_pickle", builder()));
- public static final Item WHITE_WOOL = register(new BlockItem("white_wool", builder()));
- public static final Item ORANGE_WOOL = register(new BlockItem("orange_wool", builder()));
- public static final Item MAGENTA_WOOL = register(new BlockItem("magenta_wool", builder()));
- public static final Item LIGHT_BLUE_WOOL = register(new BlockItem("light_blue_wool", builder()));
- public static final Item YELLOW_WOOL = register(new BlockItem("yellow_wool", builder()));
- public static final Item LIME_WOOL = register(new BlockItem("lime_wool", builder()));
- public static final Item PINK_WOOL = register(new BlockItem("pink_wool", builder()));
- public static final Item GRAY_WOOL = register(new BlockItem("gray_wool", builder()));
- public static final Item LIGHT_GRAY_WOOL = register(new BlockItem("light_gray_wool", builder()));
- public static final Item CYAN_WOOL = register(new BlockItem("cyan_wool", builder()));
- public static final Item PURPLE_WOOL = register(new BlockItem("purple_wool", builder()));
- public static final Item BLUE_WOOL = register(new BlockItem("blue_wool", builder()));
- public static final Item BROWN_WOOL = register(new BlockItem("brown_wool", builder()));
- public static final Item GREEN_WOOL = register(new BlockItem("green_wool", builder()));
- public static final Item RED_WOOL = register(new BlockItem("red_wool", builder()));
- public static final Item BLACK_WOOL = register(new BlockItem("black_wool", builder()));
- public static final Item DANDELION = register(new BlockItem("dandelion", builder()));
- public static final Item POPPY = register(new BlockItem("poppy", builder()));
- public static final Item BLUE_ORCHID = register(new BlockItem("blue_orchid", builder()));
- public static final Item ALLIUM = register(new BlockItem("allium", builder()));
- public static final Item AZURE_BLUET = register(new BlockItem("azure_bluet", builder()));
- public static final Item RED_TULIP = register(new BlockItem("red_tulip", builder()));
- public static final Item ORANGE_TULIP = register(new BlockItem("orange_tulip", builder()));
- public static final Item WHITE_TULIP = register(new BlockItem("white_tulip", builder()));
- public static final Item PINK_TULIP = register(new BlockItem("pink_tulip", builder()));
- public static final Item OXEYE_DAISY = register(new BlockItem("oxeye_daisy", builder()));
- public static final Item CORNFLOWER = register(new BlockItem("cornflower", builder()));
- public static final Item LILY_OF_THE_VALLEY = register(new BlockItem("lily_of_the_valley", builder()));
- public static final Item WITHER_ROSE = register(new BlockItem("wither_rose", builder()));
- public static final Item TORCHFLOWER = register(new BlockItem("torchflower", builder()));
- public static final Item PITCHER_PLANT = register(new BlockItem("pitcher_plant", builder()));
- public static final Item SPORE_BLOSSOM = register(new BlockItem("spore_blossom", builder()));
- public static final Item BROWN_MUSHROOM = register(new BlockItem("brown_mushroom", builder()));
- public static final Item RED_MUSHROOM = register(new BlockItem("red_mushroom", builder()));
- public static final Item CRIMSON_FUNGUS = register(new BlockItem("crimson_fungus", builder()));
- public static final Item WARPED_FUNGUS = register(new BlockItem("warped_fungus", builder()));
- public static final Item CRIMSON_ROOTS = register(new BlockItem("crimson_roots", builder()));
- public static final Item WARPED_ROOTS = register(new BlockItem("warped_roots", builder()));
- public static final Item NETHER_SPROUTS = register(new BlockItem("nether_sprouts", builder()));
- public static final Item WEEPING_VINES = register(new BlockItem("weeping_vines", builder()));
- public static final Item TWISTING_VINES = register(new BlockItem("twisting_vines", builder()));
- public static final Item SUGAR_CANE = register(new BlockItem("sugar_cane", builder()));
- public static final Item KELP = register(new BlockItem("kelp", builder()));
- public static final Item MOSS_CARPET = register(new BlockItem("moss_carpet", builder()));
- public static final Item PINK_PETALS = register(new BlockItem("pink_petals", builder()));
- public static final Item MOSS_BLOCK = register(new BlockItem("moss_block", builder()));
- public static final Item HANGING_ROOTS = register(new BlockItem("hanging_roots", builder()));
- public static final Item BIG_DRIPLEAF = register(new BlockItem("big_dripleaf", builder()));
- public static final Item SMALL_DRIPLEAF = register(new BlockItem("small_dripleaf", builder()));
- public static final Item BAMBOO = register(new BlockItem("bamboo", builder()));
- public static final Item OAK_SLAB = register(new BlockItem("oak_slab", builder()));
- public static final Item SPRUCE_SLAB = register(new BlockItem("spruce_slab", builder()));
- public static final Item BIRCH_SLAB = register(new BlockItem("birch_slab", builder()));
- public static final Item JUNGLE_SLAB = register(new BlockItem("jungle_slab", builder()));
- public static final Item ACACIA_SLAB = register(new BlockItem("acacia_slab", builder()));
- public static final Item CHERRY_SLAB = register(new BlockItem("cherry_slab", builder()));
- public static final Item DARK_OAK_SLAB = register(new BlockItem("dark_oak_slab", builder()));
- public static final Item MANGROVE_SLAB = register(new BlockItem("mangrove_slab", builder()));
- public static final Item BAMBOO_SLAB = register(new BlockItem("bamboo_slab", builder()));
- public static final Item BAMBOO_MOSAIC_SLAB = register(new BlockItem("bamboo_mosaic_slab", builder()));
- public static final Item CRIMSON_SLAB = register(new BlockItem("crimson_slab", builder()));
- public static final Item WARPED_SLAB = register(new BlockItem("warped_slab", builder()));
- public static final Item STONE_SLAB = register(new BlockItem("stone_slab", builder()));
- public static final Item SMOOTH_STONE_SLAB = register(new BlockItem("smooth_stone_slab", builder()));
- public static final Item SANDSTONE_SLAB = register(new BlockItem("sandstone_slab", builder()));
- public static final Item CUT_SANDSTONE_SLAB = register(new BlockItem("cut_sandstone_slab", builder()));
- public static final Item PETRIFIED_OAK_SLAB = register(new BlockItem("petrified_oak_slab", builder()));
- public static final Item COBBLESTONE_SLAB = register(new BlockItem("cobblestone_slab", builder()));
- public static final Item BRICK_SLAB = register(new BlockItem("brick_slab", builder()));
- public static final Item STONE_BRICK_SLAB = register(new BlockItem("stone_brick_slab", builder()));
- public static final Item MUD_BRICK_SLAB = register(new BlockItem("mud_brick_slab", builder()));
- public static final Item NETHER_BRICK_SLAB = register(new BlockItem("nether_brick_slab", builder()));
- public static final Item QUARTZ_SLAB = register(new BlockItem("quartz_slab", builder()));
- public static final Item RED_SANDSTONE_SLAB = register(new BlockItem("red_sandstone_slab", builder()));
- public static final Item CUT_RED_SANDSTONE_SLAB = register(new BlockItem("cut_red_sandstone_slab", builder()));
- public static final Item PURPUR_SLAB = register(new BlockItem("purpur_slab", builder()));
- public static final Item PRISMARINE_SLAB = register(new BlockItem("prismarine_slab", builder()));
- public static final Item PRISMARINE_BRICK_SLAB = register(new BlockItem("prismarine_brick_slab", builder()));
- public static final Item DARK_PRISMARINE_SLAB = register(new BlockItem("dark_prismarine_slab", builder()));
- public static final Item SMOOTH_QUARTZ = register(new BlockItem("smooth_quartz", builder()));
- public static final Item SMOOTH_RED_SANDSTONE = register(new BlockItem("smooth_red_sandstone", builder()));
- public static final Item SMOOTH_SANDSTONE = register(new BlockItem("smooth_sandstone", builder()));
- public static final Item SMOOTH_STONE = register(new BlockItem("smooth_stone", builder()));
- public static final Item BRICKS = register(new BlockItem("bricks", builder()));
- public static final Item BOOKSHELF = register(new BlockItem("bookshelf", builder()));
- public static final Item CHISELED_BOOKSHELF = register(new BlockItem("chiseled_bookshelf", builder()));
- public static final Item DECORATED_POT = register(new DecoratedPotItem("decorated_pot", builder()));
- public static final Item MOSSY_COBBLESTONE = register(new BlockItem("mossy_cobblestone", builder()));
- public static final Item OBSIDIAN = register(new BlockItem("obsidian", builder()));
- public static final Item TORCH = register(new BlockItem("torch", builder()));
- public static final Item END_ROD = register(new BlockItem("end_rod", builder()));
- public static final Item CHORUS_PLANT = register(new BlockItem("chorus_plant", builder()));
- public static final Item CHORUS_FLOWER = register(new BlockItem("chorus_flower", builder()));
- public static final Item PURPUR_BLOCK = register(new BlockItem("purpur_block", builder()));
- public static final Item PURPUR_PILLAR = register(new BlockItem("purpur_pillar", builder()));
- public static final Item PURPUR_STAIRS = register(new BlockItem("purpur_stairs", builder()));
- public static final Item SPAWNER = register(new BlockItem("spawner", builder()));
- public static final Item CHEST = register(new BlockItem("chest", builder()));
- public static final Item CRAFTING_TABLE = register(new BlockItem("crafting_table", builder()));
- public static final Item FARMLAND = register(new BlockItem("farmland", builder()));
- public static final Item FURNACE = register(new BlockItem("furnace", builder()));
- public static final Item LADDER = register(new BlockItem("ladder", builder()));
- public static final Item COBBLESTONE_STAIRS = register(new BlockItem("cobblestone_stairs", builder()));
- public static final Item SNOW = register(new BlockItem("snow", builder()));
- public static final Item ICE = register(new BlockItem("ice", builder()));
- public static final Item SNOW_BLOCK = register(new BlockItem("snow_block", builder()));
- public static final Item CACTUS = register(new BlockItem("cactus", builder()));
- public static final Item CLAY = register(new BlockItem("clay", builder()));
- public static final Item JUKEBOX = register(new BlockItem("jukebox", builder()));
- public static final Item OAK_FENCE = register(new BlockItem("oak_fence", builder()));
- public static final Item SPRUCE_FENCE = register(new BlockItem("spruce_fence", builder()));
- public static final Item BIRCH_FENCE = register(new BlockItem("birch_fence", builder()));
- public static final Item JUNGLE_FENCE = register(new BlockItem("jungle_fence", builder()));
- public static final Item ACACIA_FENCE = register(new BlockItem("acacia_fence", builder()));
- public static final Item CHERRY_FENCE = register(new BlockItem("cherry_fence", builder()));
- public static final Item DARK_OAK_FENCE = register(new BlockItem("dark_oak_fence", builder()));
- public static final Item MANGROVE_FENCE = register(new BlockItem("mangrove_fence", builder()));
- public static final Item BAMBOO_FENCE = register(new BlockItem("bamboo_fence", builder()));
- public static final Item CRIMSON_FENCE = register(new BlockItem("crimson_fence", builder()));
- public static final Item WARPED_FENCE = register(new BlockItem("warped_fence", builder()));
- public static final Item PUMPKIN = register(new BlockItem("pumpkin", builder()));
- public static final Item CARVED_PUMPKIN = register(new BlockItem("carved_pumpkin", builder()));
- public static final Item JACK_O_LANTERN = register(new BlockItem("jack_o_lantern", builder()));
- public static final Item NETHERRACK = register(new BlockItem("netherrack", builder()));
- public static final Item SOUL_SAND = register(new BlockItem("soul_sand", builder()));
- public static final Item SOUL_SOIL = register(new BlockItem("soul_soil", builder()));
- public static final Item BASALT = register(new BlockItem("basalt", builder()));
- public static final Item POLISHED_BASALT = register(new BlockItem("polished_basalt", builder()));
- public static final Item SMOOTH_BASALT = register(new BlockItem("smooth_basalt", builder()));
- public static final Item SOUL_TORCH = register(new BlockItem("soul_torch", builder()));
- public static final Item GLOWSTONE = register(new BlockItem("glowstone", builder()));
- public static final Item INFESTED_STONE = register(new BlockItem("infested_stone", builder()));
- public static final Item INFESTED_COBBLESTONE = register(new BlockItem("infested_cobblestone", builder()));
- public static final Item INFESTED_STONE_BRICKS = register(new BlockItem("infested_stone_bricks", builder()));
- public static final Item INFESTED_MOSSY_STONE_BRICKS = register(new BlockItem("infested_mossy_stone_bricks", builder()));
- public static final Item INFESTED_CRACKED_STONE_BRICKS = register(new BlockItem("infested_cracked_stone_bricks", builder()));
- public static final Item INFESTED_CHISELED_STONE_BRICKS = register(new BlockItem("infested_chiseled_stone_bricks", builder()));
- public static final Item INFESTED_DEEPSLATE = register(new BlockItem("infested_deepslate", builder()));
- public static final Item STONE_BRICKS = register(new BlockItem("stone_bricks", builder()));
- public static final Item MOSSY_STONE_BRICKS = register(new BlockItem("mossy_stone_bricks", builder()));
- public static final Item CRACKED_STONE_BRICKS = register(new BlockItem("cracked_stone_bricks", builder()));
- public static final Item CHISELED_STONE_BRICKS = register(new BlockItem("chiseled_stone_bricks", builder()));
- public static final Item PACKED_MUD = register(new BlockItem("packed_mud", builder()));
- public static final Item MUD_BRICKS = register(new BlockItem("mud_bricks", builder()));
- public static final Item DEEPSLATE_BRICKS = register(new BlockItem("deepslate_bricks", builder()));
- public static final Item CRACKED_DEEPSLATE_BRICKS = register(new BlockItem("cracked_deepslate_bricks", builder()));
- public static final Item DEEPSLATE_TILES = register(new BlockItem("deepslate_tiles", builder()));
- public static final Item CRACKED_DEEPSLATE_TILES = register(new BlockItem("cracked_deepslate_tiles", builder()));
- public static final Item CHISELED_DEEPSLATE = register(new BlockItem("chiseled_deepslate", builder()));
- public static final Item REINFORCED_DEEPSLATE = register(new BlockItem("reinforced_deepslate", builder()));
- public static final Item BROWN_MUSHROOM_BLOCK = register(new BlockItem("brown_mushroom_block", builder()));
- public static final Item RED_MUSHROOM_BLOCK = register(new BlockItem("red_mushroom_block", builder()));
- public static final Item MUSHROOM_STEM = register(new BlockItem("mushroom_stem", builder()));
- public static final Item IRON_BARS = register(new BlockItem("iron_bars", builder()));
- public static final Item CHAIN = register(new BlockItem("chain", builder()));
- public static final Item GLASS_PANE = register(new BlockItem("glass_pane", builder()));
- public static final Item MELON = register(new BlockItem("melon", builder()));
- public static final Item VINE = register(new BlockItem("vine", builder()));
- public static final Item GLOW_LICHEN = register(new BlockItem("glow_lichen", builder()));
- public static final Item BRICK_STAIRS = register(new BlockItem("brick_stairs", builder()));
- public static final Item STONE_BRICK_STAIRS = register(new BlockItem("stone_brick_stairs", builder()));
- public static final Item MUD_BRICK_STAIRS = register(new BlockItem("mud_brick_stairs", builder()));
- public static final Item MYCELIUM = register(new BlockItem("mycelium", builder()));
- public static final Item LILY_PAD = register(new BlockItem("lily_pad", builder()));
- public static final Item NETHER_BRICKS = register(new BlockItem("nether_bricks", builder()));
- public static final Item CRACKED_NETHER_BRICKS = register(new BlockItem("cracked_nether_bricks", builder()));
- public static final Item CHISELED_NETHER_BRICKS = register(new BlockItem("chiseled_nether_bricks", builder()));
- public static final Item NETHER_BRICK_FENCE = register(new BlockItem("nether_brick_fence", builder()));
- public static final Item NETHER_BRICK_STAIRS = register(new BlockItem("nether_brick_stairs", builder()));
- public static final Item SCULK = register(new BlockItem("sculk", builder()));
- public static final Item SCULK_VEIN = register(new BlockItem("sculk_vein", builder()));
- public static final Item SCULK_CATALYST = register(new BlockItem("sculk_catalyst", builder()));
- public static final Item SCULK_SHRIEKER = register(new BlockItem("sculk_shrieker", builder()));
- public static final Item ENCHANTING_TABLE = register(new BlockItem("enchanting_table", builder()));
- public static final Item END_PORTAL_FRAME = register(new BlockItem("end_portal_frame", builder()));
- public static final Item END_STONE = register(new BlockItem("end_stone", builder()));
- public static final Item END_STONE_BRICKS = register(new BlockItem("end_stone_bricks", builder()));
- public static final Item DRAGON_EGG = register(new BlockItem("dragon_egg", builder()));
- public static final Item SANDSTONE_STAIRS = register(new BlockItem("sandstone_stairs", builder()));
- public static final Item ENDER_CHEST = register(new BlockItem("ender_chest", builder()));
- public static final Item EMERALD_BLOCK = register(new BlockItem("emerald_block", builder()));
- public static final Item OAK_STAIRS = register(new BlockItem("oak_stairs", builder()));
- public static final Item SPRUCE_STAIRS = register(new BlockItem("spruce_stairs", builder()));
- public static final Item BIRCH_STAIRS = register(new BlockItem("birch_stairs", builder()));
- public static final Item JUNGLE_STAIRS = register(new BlockItem("jungle_stairs", builder()));
- public static final Item ACACIA_STAIRS = register(new BlockItem("acacia_stairs", builder()));
- public static final Item CHERRY_STAIRS = register(new BlockItem("cherry_stairs", builder()));
- public static final Item DARK_OAK_STAIRS = register(new BlockItem("dark_oak_stairs", builder()));
- public static final Item MANGROVE_STAIRS = register(new BlockItem("mangrove_stairs", builder()));
- public static final Item BAMBOO_STAIRS = register(new BlockItem("bamboo_stairs", builder()));
- public static final Item BAMBOO_MOSAIC_STAIRS = register(new BlockItem("bamboo_mosaic_stairs", builder()));
- public static final Item CRIMSON_STAIRS = register(new BlockItem("crimson_stairs", builder()));
- public static final Item WARPED_STAIRS = register(new BlockItem("warped_stairs", builder()));
- public static final Item COMMAND_BLOCK = register(new BlockItem("command_block", builder()));
- public static final Item BEACON = register(new BlockItem("beacon", builder()));
- public static final Item COBBLESTONE_WALL = register(new BlockItem("cobblestone_wall", builder()));
- public static final Item MOSSY_COBBLESTONE_WALL = register(new BlockItem("mossy_cobblestone_wall", builder()));
- public static final Item BRICK_WALL = register(new BlockItem("brick_wall", builder()));
- public static final Item PRISMARINE_WALL = register(new BlockItem("prismarine_wall", builder()));
- public static final Item RED_SANDSTONE_WALL = register(new BlockItem("red_sandstone_wall", builder()));
- public static final Item MOSSY_STONE_BRICK_WALL = register(new BlockItem("mossy_stone_brick_wall", builder()));
- public static final Item GRANITE_WALL = register(new BlockItem("granite_wall", builder()));
- public static final Item STONE_BRICK_WALL = register(new BlockItem("stone_brick_wall", builder()));
- public static final Item MUD_BRICK_WALL = register(new BlockItem("mud_brick_wall", builder()));
- public static final Item NETHER_BRICK_WALL = register(new BlockItem("nether_brick_wall", builder()));
- public static final Item ANDESITE_WALL = register(new BlockItem("andesite_wall", builder()));
- public static final Item RED_NETHER_BRICK_WALL = register(new BlockItem("red_nether_brick_wall", builder()));
- public static final Item SANDSTONE_WALL = register(new BlockItem("sandstone_wall", builder()));
- public static final Item END_STONE_BRICK_WALL = register(new BlockItem("end_stone_brick_wall", builder()));
- public static final Item DIORITE_WALL = register(new BlockItem("diorite_wall", builder()));
- public static final Item BLACKSTONE_WALL = register(new BlockItem("blackstone_wall", builder()));
- public static final Item POLISHED_BLACKSTONE_WALL = register(new BlockItem("polished_blackstone_wall", builder()));
- public static final Item POLISHED_BLACKSTONE_BRICK_WALL = register(new BlockItem("polished_blackstone_brick_wall", builder()));
- public static final Item COBBLED_DEEPSLATE_WALL = register(new BlockItem("cobbled_deepslate_wall", builder()));
- public static final Item POLISHED_DEEPSLATE_WALL = register(new BlockItem("polished_deepslate_wall", builder()));
- public static final Item DEEPSLATE_BRICK_WALL = register(new BlockItem("deepslate_brick_wall", builder()));
- public static final Item DEEPSLATE_TILE_WALL = register(new BlockItem("deepslate_tile_wall", builder()));
- public static final Item ANVIL = register(new BlockItem("anvil", builder()));
- public static final Item CHIPPED_ANVIL = register(new BlockItem("chipped_anvil", builder()));
- public static final Item DAMAGED_ANVIL = register(new BlockItem("damaged_anvil", builder()));
- public static final Item CHISELED_QUARTZ_BLOCK = register(new BlockItem("chiseled_quartz_block", builder()));
- public static final Item QUARTZ_BLOCK = register(new BlockItem("quartz_block", builder()));
- public static final Item QUARTZ_BRICKS = register(new BlockItem("quartz_bricks", builder()));
- public static final Item QUARTZ_PILLAR = register(new BlockItem("quartz_pillar", builder()));
- public static final Item QUARTZ_STAIRS = register(new BlockItem("quartz_stairs", builder()));
- public static final Item WHITE_TERRACOTTA = register(new BlockItem("white_terracotta", builder()));
- public static final Item ORANGE_TERRACOTTA = register(new BlockItem("orange_terracotta", builder()));
- public static final Item MAGENTA_TERRACOTTA = register(new BlockItem("magenta_terracotta", builder()));
- public static final Item LIGHT_BLUE_TERRACOTTA = register(new BlockItem("light_blue_terracotta", builder()));
- public static final Item YELLOW_TERRACOTTA = register(new BlockItem("yellow_terracotta", builder()));
- public static final Item LIME_TERRACOTTA = register(new BlockItem("lime_terracotta", builder()));
- public static final Item PINK_TERRACOTTA = register(new BlockItem("pink_terracotta", builder()));
- public static final Item GRAY_TERRACOTTA = register(new BlockItem("gray_terracotta", builder()));
- public static final Item LIGHT_GRAY_TERRACOTTA = register(new BlockItem("light_gray_terracotta", builder()));
- public static final Item CYAN_TERRACOTTA = register(new BlockItem("cyan_terracotta", builder()));
- public static final Item PURPLE_TERRACOTTA = register(new BlockItem("purple_terracotta", builder()));
- public static final Item BLUE_TERRACOTTA = register(new BlockItem("blue_terracotta", builder()));
- public static final Item BROWN_TERRACOTTA = register(new BlockItem("brown_terracotta", builder()));
- public static final Item GREEN_TERRACOTTA = register(new BlockItem("green_terracotta", builder()));
- public static final Item RED_TERRACOTTA = register(new BlockItem("red_terracotta", builder()));
- public static final Item BLACK_TERRACOTTA = register(new BlockItem("black_terracotta", builder()));
- public static final Item BARRIER = register(new BlockItem("barrier", builder()));
- public static final Item LIGHT = register(new BlockItem("light", builder()));
- public static final Item HAY_BLOCK = register(new BlockItem("hay_block", builder()));
- public static final Item WHITE_CARPET = register(new BlockItem("white_carpet", builder()));
- public static final Item ORANGE_CARPET = register(new BlockItem("orange_carpet", builder()));
- public static final Item MAGENTA_CARPET = register(new BlockItem("magenta_carpet", builder()));
- public static final Item LIGHT_BLUE_CARPET = register(new BlockItem("light_blue_carpet", builder()));
- public static final Item YELLOW_CARPET = register(new BlockItem("yellow_carpet", builder()));
- public static final Item LIME_CARPET = register(new BlockItem("lime_carpet", builder()));
- public static final Item PINK_CARPET = register(new BlockItem("pink_carpet", builder()));
- public static final Item GRAY_CARPET = register(new BlockItem("gray_carpet", builder()));
- public static final Item LIGHT_GRAY_CARPET = register(new BlockItem("light_gray_carpet", builder()));
- public static final Item CYAN_CARPET = register(new BlockItem("cyan_carpet", builder()));
- public static final Item PURPLE_CARPET = register(new BlockItem("purple_carpet", builder()));
- public static final Item BLUE_CARPET = register(new BlockItem("blue_carpet", builder()));
- public static final Item BROWN_CARPET = register(new BlockItem("brown_carpet", builder()));
- public static final Item GREEN_CARPET = register(new BlockItem("green_carpet", builder()));
- public static final Item RED_CARPET = register(new BlockItem("red_carpet", builder()));
- public static final Item BLACK_CARPET = register(new BlockItem("black_carpet", builder()));
- public static final Item TERRACOTTA = register(new BlockItem("terracotta", builder()));
- public static final Item PACKED_ICE = register(new BlockItem("packed_ice", builder()));
- public static final Item DIRT_PATH = register(new BlockItem("dirt_path", builder()));
- public static final Item SUNFLOWER = register(new BlockItem("sunflower", builder()));
- public static final Item LILAC = register(new BlockItem("lilac", builder()));
- public static final Item ROSE_BUSH = register(new BlockItem("rose_bush", builder()));
- public static final Item PEONY = register(new BlockItem("peony", builder()));
- public static final Item TALL_GRASS = register(new BlockItem("tall_grass", builder()));
- public static final Item LARGE_FERN = register(new BlockItem("large_fern", builder()));
- public static final Item WHITE_STAINED_GLASS = register(new BlockItem("white_stained_glass", builder()));
- public static final Item ORANGE_STAINED_GLASS = register(new BlockItem("orange_stained_glass", builder()));
- public static final Item MAGENTA_STAINED_GLASS = register(new BlockItem("magenta_stained_glass", builder()));
- public static final Item LIGHT_BLUE_STAINED_GLASS = register(new BlockItem("light_blue_stained_glass", builder()));
- public static final Item YELLOW_STAINED_GLASS = register(new BlockItem("yellow_stained_glass", builder()));
- public static final Item LIME_STAINED_GLASS = register(new BlockItem("lime_stained_glass", builder()));
- public static final Item PINK_STAINED_GLASS = register(new BlockItem("pink_stained_glass", builder()));
- public static final Item GRAY_STAINED_GLASS = register(new BlockItem("gray_stained_glass", builder()));
- public static final Item LIGHT_GRAY_STAINED_GLASS = register(new BlockItem("light_gray_stained_glass", builder()));
- public static final Item CYAN_STAINED_GLASS = register(new BlockItem("cyan_stained_glass", builder()));
- public static final Item PURPLE_STAINED_GLASS = register(new BlockItem("purple_stained_glass", builder()));
- public static final Item BLUE_STAINED_GLASS = register(new BlockItem("blue_stained_glass", builder()));
- public static final Item BROWN_STAINED_GLASS = register(new BlockItem("brown_stained_glass", builder()));
- public static final Item GREEN_STAINED_GLASS = register(new BlockItem("green_stained_glass", builder()));
- public static final Item RED_STAINED_GLASS = register(new BlockItem("red_stained_glass", builder()));
- public static final Item BLACK_STAINED_GLASS = register(new BlockItem("black_stained_glass", builder()));
- public static final Item WHITE_STAINED_GLASS_PANE = register(new BlockItem("white_stained_glass_pane", builder()));
- public static final Item ORANGE_STAINED_GLASS_PANE = register(new BlockItem("orange_stained_glass_pane", builder()));
- public static final Item MAGENTA_STAINED_GLASS_PANE = register(new BlockItem("magenta_stained_glass_pane", builder()));
- public static final Item LIGHT_BLUE_STAINED_GLASS_PANE = register(new BlockItem("light_blue_stained_glass_pane", builder()));
- public static final Item YELLOW_STAINED_GLASS_PANE = register(new BlockItem("yellow_stained_glass_pane", builder()));
- public static final Item LIME_STAINED_GLASS_PANE = register(new BlockItem("lime_stained_glass_pane", builder()));
- public static final Item PINK_STAINED_GLASS_PANE = register(new BlockItem("pink_stained_glass_pane", builder()));
- public static final Item GRAY_STAINED_GLASS_PANE = register(new BlockItem("gray_stained_glass_pane", builder()));
- public static final Item LIGHT_GRAY_STAINED_GLASS_PANE = register(new BlockItem("light_gray_stained_glass_pane", builder()));
- public static final Item CYAN_STAINED_GLASS_PANE = register(new BlockItem("cyan_stained_glass_pane", builder()));
- public static final Item PURPLE_STAINED_GLASS_PANE = register(new BlockItem("purple_stained_glass_pane", builder()));
- public static final Item BLUE_STAINED_GLASS_PANE = register(new BlockItem("blue_stained_glass_pane", builder()));
- public static final Item BROWN_STAINED_GLASS_PANE = register(new BlockItem("brown_stained_glass_pane", builder()));
- public static final Item GREEN_STAINED_GLASS_PANE = register(new BlockItem("green_stained_glass_pane", builder()));
- public static final Item RED_STAINED_GLASS_PANE = register(new BlockItem("red_stained_glass_pane", builder()));
- public static final Item BLACK_STAINED_GLASS_PANE = register(new BlockItem("black_stained_glass_pane", builder()));
- public static final Item PRISMARINE = register(new BlockItem("prismarine", builder()));
- public static final Item PRISMARINE_BRICKS = register(new BlockItem("prismarine_bricks", builder()));
- public static final Item DARK_PRISMARINE = register(new BlockItem("dark_prismarine", builder()));
- public static final Item PRISMARINE_STAIRS = register(new BlockItem("prismarine_stairs", builder()));
- public static final Item PRISMARINE_BRICK_STAIRS = register(new BlockItem("prismarine_brick_stairs", builder()));
- public static final Item DARK_PRISMARINE_STAIRS = register(new BlockItem("dark_prismarine_stairs", builder()));
- public static final Item SEA_LANTERN = register(new BlockItem("sea_lantern", builder()));
- public static final Item RED_SANDSTONE = register(new BlockItem("red_sandstone", builder()));
- public static final Item CHISELED_RED_SANDSTONE = register(new BlockItem("chiseled_red_sandstone", builder()));
- public static final Item CUT_RED_SANDSTONE = register(new BlockItem("cut_red_sandstone", builder()));
- public static final Item RED_SANDSTONE_STAIRS = register(new BlockItem("red_sandstone_stairs", builder()));
- public static final Item REPEATING_COMMAND_BLOCK = register(new BlockItem("repeating_command_block", builder()));
- public static final Item CHAIN_COMMAND_BLOCK = register(new BlockItem("chain_command_block", builder()));
- public static final Item MAGMA_BLOCK = register(new BlockItem("magma_block", builder()));
- public static final Item NETHER_WART_BLOCK = register(new BlockItem("nether_wart_block", builder()));
- public static final Item WARPED_WART_BLOCK = register(new BlockItem("warped_wart_block", builder()));
- public static final Item RED_NETHER_BRICKS = register(new BlockItem("red_nether_bricks", builder()));
- public static final Item BONE_BLOCK = register(new BlockItem("bone_block", builder()));
- public static final Item STRUCTURE_VOID = register(new BlockItem("structure_void", builder()));
- public static final Item SHULKER_BOX = register(new ShulkerBoxItem("shulker_box", builder().stackSize(1)));
- public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem("white_shulker_box", builder().stackSize(1)));
- public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem("orange_shulker_box", builder().stackSize(1)));
- public static final Item MAGENTA_SHULKER_BOX = register(new ShulkerBoxItem("magenta_shulker_box", builder().stackSize(1)));
- public static final Item LIGHT_BLUE_SHULKER_BOX = register(new ShulkerBoxItem("light_blue_shulker_box", builder().stackSize(1)));
- public static final Item YELLOW_SHULKER_BOX = register(new ShulkerBoxItem("yellow_shulker_box", builder().stackSize(1)));
- public static final Item LIME_SHULKER_BOX = register(new ShulkerBoxItem("lime_shulker_box", builder().stackSize(1)));
- public static final Item PINK_SHULKER_BOX = register(new ShulkerBoxItem("pink_shulker_box", builder().stackSize(1)));
- public static final Item GRAY_SHULKER_BOX = register(new ShulkerBoxItem("gray_shulker_box", builder().stackSize(1)));
- public static final Item LIGHT_GRAY_SHULKER_BOX = register(new ShulkerBoxItem("light_gray_shulker_box", builder().stackSize(1)));
- public static final Item CYAN_SHULKER_BOX = register(new ShulkerBoxItem("cyan_shulker_box", builder().stackSize(1)));
- public static final Item PURPLE_SHULKER_BOX = register(new ShulkerBoxItem("purple_shulker_box", builder().stackSize(1)));
- public static final Item BLUE_SHULKER_BOX = register(new ShulkerBoxItem("blue_shulker_box", builder().stackSize(1)));
- public static final Item BROWN_SHULKER_BOX = register(new ShulkerBoxItem("brown_shulker_box", builder().stackSize(1)));
- public static final Item GREEN_SHULKER_BOX = register(new ShulkerBoxItem("green_shulker_box", builder().stackSize(1)));
- public static final Item RED_SHULKER_BOX = register(new ShulkerBoxItem("red_shulker_box", builder().stackSize(1)));
- public static final Item BLACK_SHULKER_BOX = register(new ShulkerBoxItem("black_shulker_box", builder().stackSize(1)));
- public static final Item WHITE_GLAZED_TERRACOTTA = register(new BlockItem("white_glazed_terracotta", builder()));
- public static final Item ORANGE_GLAZED_TERRACOTTA = register(new BlockItem("orange_glazed_terracotta", builder()));
- public static final Item MAGENTA_GLAZED_TERRACOTTA = register(new BlockItem("magenta_glazed_terracotta", builder()));
- public static final Item LIGHT_BLUE_GLAZED_TERRACOTTA = register(new BlockItem("light_blue_glazed_terracotta", builder()));
- public static final Item YELLOW_GLAZED_TERRACOTTA = register(new BlockItem("yellow_glazed_terracotta", builder()));
- public static final Item LIME_GLAZED_TERRACOTTA = register(new BlockItem("lime_glazed_terracotta", builder()));
- public static final Item PINK_GLAZED_TERRACOTTA = register(new BlockItem("pink_glazed_terracotta", builder()));
- public static final Item GRAY_GLAZED_TERRACOTTA = register(new BlockItem("gray_glazed_terracotta", builder()));
- public static final Item LIGHT_GRAY_GLAZED_TERRACOTTA = register(new BlockItem("light_gray_glazed_terracotta", builder()));
- public static final Item CYAN_GLAZED_TERRACOTTA = register(new BlockItem("cyan_glazed_terracotta", builder()));
- public static final Item PURPLE_GLAZED_TERRACOTTA = register(new BlockItem("purple_glazed_terracotta", builder()));
- public static final Item BLUE_GLAZED_TERRACOTTA = register(new BlockItem("blue_glazed_terracotta", builder()));
- public static final Item BROWN_GLAZED_TERRACOTTA = register(new BlockItem("brown_glazed_terracotta", builder()));
- public static final Item GREEN_GLAZED_TERRACOTTA = register(new BlockItem("green_glazed_terracotta", builder()));
- public static final Item RED_GLAZED_TERRACOTTA = register(new BlockItem("red_glazed_terracotta", builder()));
- public static final Item BLACK_GLAZED_TERRACOTTA = register(new BlockItem("black_glazed_terracotta", builder()));
- public static final Item WHITE_CONCRETE = register(new BlockItem("white_concrete", builder()));
- public static final Item ORANGE_CONCRETE = register(new BlockItem("orange_concrete", builder()));
- public static final Item MAGENTA_CONCRETE = register(new BlockItem("magenta_concrete", builder()));
- public static final Item LIGHT_BLUE_CONCRETE = register(new BlockItem("light_blue_concrete", builder()));
- public static final Item YELLOW_CONCRETE = register(new BlockItem("yellow_concrete", builder()));
- public static final Item LIME_CONCRETE = register(new BlockItem("lime_concrete", builder()));
- public static final Item PINK_CONCRETE = register(new BlockItem("pink_concrete", builder()));
- public static final Item GRAY_CONCRETE = register(new BlockItem("gray_concrete", builder()));
- public static final Item LIGHT_GRAY_CONCRETE = register(new BlockItem("light_gray_concrete", builder()));
- public static final Item CYAN_CONCRETE = register(new BlockItem("cyan_concrete", builder()));
- public static final Item PURPLE_CONCRETE = register(new BlockItem("purple_concrete", builder()));
- public static final Item BLUE_CONCRETE = register(new BlockItem("blue_concrete", builder()));
- public static final Item BROWN_CONCRETE = register(new BlockItem("brown_concrete", builder()));
- public static final Item GREEN_CONCRETE = register(new BlockItem("green_concrete", builder()));
- public static final Item RED_CONCRETE = register(new BlockItem("red_concrete", builder()));
- public static final Item BLACK_CONCRETE = register(new BlockItem("black_concrete", builder()));
- public static final Item WHITE_CONCRETE_POWDER = register(new BlockItem("white_concrete_powder", builder()));
- public static final Item ORANGE_CONCRETE_POWDER = register(new BlockItem("orange_concrete_powder", builder()));
- public static final Item MAGENTA_CONCRETE_POWDER = register(new BlockItem("magenta_concrete_powder", builder()));
- public static final Item LIGHT_BLUE_CONCRETE_POWDER = register(new BlockItem("light_blue_concrete_powder", builder()));
- public static final Item YELLOW_CONCRETE_POWDER = register(new BlockItem("yellow_concrete_powder", builder()));
- public static final Item LIME_CONCRETE_POWDER = register(new BlockItem("lime_concrete_powder", builder()));
- public static final Item PINK_CONCRETE_POWDER = register(new BlockItem("pink_concrete_powder", builder()));
- public static final Item GRAY_CONCRETE_POWDER = register(new BlockItem("gray_concrete_powder", builder()));
- public static final Item LIGHT_GRAY_CONCRETE_POWDER = register(new BlockItem("light_gray_concrete_powder", builder()));
- public static final Item CYAN_CONCRETE_POWDER = register(new BlockItem("cyan_concrete_powder", builder()));
- public static final Item PURPLE_CONCRETE_POWDER = register(new BlockItem("purple_concrete_powder", builder()));
- public static final Item BLUE_CONCRETE_POWDER = register(new BlockItem("blue_concrete_powder", builder()));
- public static final Item BROWN_CONCRETE_POWDER = register(new BlockItem("brown_concrete_powder", builder()));
- public static final Item GREEN_CONCRETE_POWDER = register(new BlockItem("green_concrete_powder", builder()));
- public static final Item RED_CONCRETE_POWDER = register(new BlockItem("red_concrete_powder", builder()));
- public static final Item BLACK_CONCRETE_POWDER = register(new BlockItem("black_concrete_powder", builder()));
- public static final Item TURTLE_EGG = register(new BlockItem("turtle_egg", builder()));
- public static final Item SNIFFER_EGG = register(new BlockItem("sniffer_egg", builder()));
- public static final Item DEAD_TUBE_CORAL_BLOCK = register(new BlockItem("dead_tube_coral_block", builder()));
- public static final Item DEAD_BRAIN_CORAL_BLOCK = register(new BlockItem("dead_brain_coral_block", builder()));
- public static final Item DEAD_BUBBLE_CORAL_BLOCK = register(new BlockItem("dead_bubble_coral_block", builder()));
- public static final Item DEAD_FIRE_CORAL_BLOCK = register(new BlockItem("dead_fire_coral_block", builder()));
- public static final Item DEAD_HORN_CORAL_BLOCK = register(new BlockItem("dead_horn_coral_block", builder()));
- public static final Item TUBE_CORAL_BLOCK = register(new BlockItem("tube_coral_block", builder()));
- public static final Item BRAIN_CORAL_BLOCK = register(new BlockItem("brain_coral_block", builder()));
- public static final Item BUBBLE_CORAL_BLOCK = register(new BlockItem("bubble_coral_block", builder()));
- public static final Item FIRE_CORAL_BLOCK = register(new BlockItem("fire_coral_block", builder()));
- public static final Item HORN_CORAL_BLOCK = register(new BlockItem("horn_coral_block", builder()));
- public static final Item TUBE_CORAL = register(new BlockItem("tube_coral", builder()));
- public static final Item BRAIN_CORAL = register(new BlockItem("brain_coral", builder()));
- public static final Item BUBBLE_CORAL = register(new BlockItem("bubble_coral", builder()));
- public static final Item FIRE_CORAL = register(new BlockItem("fire_coral", builder()));
- public static final Item HORN_CORAL = register(new BlockItem("horn_coral", builder()));
- public static final Item DEAD_BRAIN_CORAL = register(new BlockItem("dead_brain_coral", builder()));
- public static final Item DEAD_BUBBLE_CORAL = register(new BlockItem("dead_bubble_coral", builder()));
- public static final Item DEAD_FIRE_CORAL = register(new BlockItem("dead_fire_coral", builder()));
- public static final Item DEAD_HORN_CORAL = register(new BlockItem("dead_horn_coral", builder()));
- public static final Item DEAD_TUBE_CORAL = register(new BlockItem("dead_tube_coral", builder()));
- public static final Item TUBE_CORAL_FAN = register(new BlockItem("tube_coral_fan", builder()));
- public static final Item BRAIN_CORAL_FAN = register(new BlockItem("brain_coral_fan", builder()));
- public static final Item BUBBLE_CORAL_FAN = register(new BlockItem("bubble_coral_fan", builder()));
- public static final Item FIRE_CORAL_FAN = register(new BlockItem("fire_coral_fan", builder()));
- public static final Item HORN_CORAL_FAN = register(new BlockItem("horn_coral_fan", builder()));
- public static final Item DEAD_TUBE_CORAL_FAN = register(new BlockItem("dead_tube_coral_fan", builder()));
- public static final Item DEAD_BRAIN_CORAL_FAN = register(new BlockItem("dead_brain_coral_fan", builder()));
- public static final Item DEAD_BUBBLE_CORAL_FAN = register(new BlockItem("dead_bubble_coral_fan", builder()));
- public static final Item DEAD_FIRE_CORAL_FAN = register(new BlockItem("dead_fire_coral_fan", builder()));
- public static final Item DEAD_HORN_CORAL_FAN = register(new BlockItem("dead_horn_coral_fan", builder()));
- public static final Item BLUE_ICE = register(new BlockItem("blue_ice", builder()));
- public static final Item CONDUIT = register(new BlockItem("conduit", builder()));
- public static final Item POLISHED_GRANITE_STAIRS = register(new BlockItem("polished_granite_stairs", builder()));
- public static final Item SMOOTH_RED_SANDSTONE_STAIRS = register(new BlockItem("smooth_red_sandstone_stairs", builder()));
- public static final Item MOSSY_STONE_BRICK_STAIRS = register(new BlockItem("mossy_stone_brick_stairs", builder()));
- public static final Item POLISHED_DIORITE_STAIRS = register(new BlockItem("polished_diorite_stairs", builder()));
- public static final Item MOSSY_COBBLESTONE_STAIRS = register(new BlockItem("mossy_cobblestone_stairs", builder()));
- public static final Item END_STONE_BRICK_STAIRS = register(new BlockItem("end_stone_brick_stairs", builder()));
- public static final Item STONE_STAIRS = register(new BlockItem("stone_stairs", builder()));
- public static final Item SMOOTH_SANDSTONE_STAIRS = register(new BlockItem("smooth_sandstone_stairs", builder()));
- public static final Item SMOOTH_QUARTZ_STAIRS = register(new BlockItem("smooth_quartz_stairs", builder()));
- public static final Item GRANITE_STAIRS = register(new BlockItem("granite_stairs", builder()));
- public static final Item ANDESITE_STAIRS = register(new BlockItem("andesite_stairs", builder()));
- public static final Item RED_NETHER_BRICK_STAIRS = register(new BlockItem("red_nether_brick_stairs", builder()));
- public static final Item POLISHED_ANDESITE_STAIRS = register(new BlockItem("polished_andesite_stairs", builder()));
- public static final Item DIORITE_STAIRS = register(new BlockItem("diorite_stairs", builder()));
- public static final Item COBBLED_DEEPSLATE_STAIRS = register(new BlockItem("cobbled_deepslate_stairs", builder()));
- public static final Item POLISHED_DEEPSLATE_STAIRS = register(new BlockItem("polished_deepslate_stairs", builder()));
- public static final Item DEEPSLATE_BRICK_STAIRS = register(new BlockItem("deepslate_brick_stairs", builder()));
- public static final Item DEEPSLATE_TILE_STAIRS = register(new BlockItem("deepslate_tile_stairs", builder()));
- public static final Item POLISHED_GRANITE_SLAB = register(new BlockItem("polished_granite_slab", builder()));
- public static final Item SMOOTH_RED_SANDSTONE_SLAB = register(new BlockItem("smooth_red_sandstone_slab", builder()));
- public static final Item MOSSY_STONE_BRICK_SLAB = register(new BlockItem("mossy_stone_brick_slab", builder()));
- public static final Item POLISHED_DIORITE_SLAB = register(new BlockItem("polished_diorite_slab", builder()));
- public static final Item MOSSY_COBBLESTONE_SLAB = register(new BlockItem("mossy_cobblestone_slab", builder()));
- public static final Item END_STONE_BRICK_SLAB = register(new BlockItem("end_stone_brick_slab", builder()));
- public static final Item SMOOTH_SANDSTONE_SLAB = register(new BlockItem("smooth_sandstone_slab", builder()));
- public static final Item SMOOTH_QUARTZ_SLAB = register(new BlockItem("smooth_quartz_slab", builder()));
- public static final Item GRANITE_SLAB = register(new BlockItem("granite_slab", builder()));
- public static final Item ANDESITE_SLAB = register(new BlockItem("andesite_slab", builder()));
- public static final Item RED_NETHER_BRICK_SLAB = register(new BlockItem("red_nether_brick_slab", builder()));
- public static final Item POLISHED_ANDESITE_SLAB = register(new BlockItem("polished_andesite_slab", builder()));
- public static final Item DIORITE_SLAB = register(new BlockItem("diorite_slab", builder()));
- public static final Item COBBLED_DEEPSLATE_SLAB = register(new BlockItem("cobbled_deepslate_slab", builder()));
- public static final Item POLISHED_DEEPSLATE_SLAB = register(new BlockItem("polished_deepslate_slab", builder()));
- public static final Item DEEPSLATE_BRICK_SLAB = register(new BlockItem("deepslate_brick_slab", builder()));
- public static final Item DEEPSLATE_TILE_SLAB = register(new BlockItem("deepslate_tile_slab", builder()));
- public static final Item SCAFFOLDING = register(new BlockItem("scaffolding", builder()));
- public static final Item REDSTONE = register(new BlockItem("redstone", builder()));
- public static final Item REDSTONE_TORCH = register(new BlockItem("redstone_torch", builder()));
- public static final Item REDSTONE_BLOCK = register(new BlockItem("redstone_block", builder()));
- public static final Item REPEATER = register(new BlockItem("repeater", builder()));
- public static final Item COMPARATOR = register(new BlockItem("comparator", builder()));
- public static final Item PISTON = register(new BlockItem("piston", builder()));
- public static final Item STICKY_PISTON = register(new BlockItem("sticky_piston", builder()));
- public static final Item SLIME_BLOCK = register(new BlockItem("slime_block", builder()));
- public static final Item HONEY_BLOCK = register(new BlockItem("honey_block", builder()));
- public static final Item OBSERVER = register(new BlockItem("observer", builder()));
- public static final Item HOPPER = register(new BlockItem("hopper", builder()));
- public static final Item DISPENSER = register(new BlockItem("dispenser", builder()));
- public static final Item DROPPER = register(new BlockItem("dropper", builder()));
- public static final Item LECTERN = register(new BlockItem("lectern", builder()));
- public static final Item TARGET = register(new BlockItem("target", builder()));
- public static final Item LEVER = register(new BlockItem("lever", builder()));
- public static final Item LIGHTNING_ROD = register(new BlockItem("lightning_rod", builder()));
- public static final Item DAYLIGHT_DETECTOR = register(new BlockItem("daylight_detector", builder()));
- public static final Item SCULK_SENSOR = register(new BlockItem("sculk_sensor", builder()));
- public static final Item CALIBRATED_SCULK_SENSOR = register(new BlockItem("calibrated_sculk_sensor", builder()));
- public static final Item TRIPWIRE_HOOK = register(new BlockItem("tripwire_hook", builder()));
- public static final Item TRAPPED_CHEST = register(new BlockItem("trapped_chest", builder()));
- public static final Item TNT = register(new BlockItem("tnt", builder()));
- public static final Item REDSTONE_LAMP = register(new BlockItem("redstone_lamp", builder()));
- public static final Item NOTE_BLOCK = register(new BlockItem("note_block", builder()));
- public static final Item STONE_BUTTON = register(new BlockItem("stone_button", builder()));
- public static final Item POLISHED_BLACKSTONE_BUTTON = register(new BlockItem("polished_blackstone_button", builder()));
- public static final Item OAK_BUTTON = register(new BlockItem("oak_button", builder()));
- public static final Item SPRUCE_BUTTON = register(new BlockItem("spruce_button", builder()));
- public static final Item BIRCH_BUTTON = register(new BlockItem("birch_button", builder()));
- public static final Item JUNGLE_BUTTON = register(new BlockItem("jungle_button", builder()));
- public static final Item ACACIA_BUTTON = register(new BlockItem("acacia_button", builder()));
- public static final Item CHERRY_BUTTON = register(new BlockItem("cherry_button", builder()));
- public static final Item DARK_OAK_BUTTON = register(new BlockItem("dark_oak_button", builder()));
- public static final Item MANGROVE_BUTTON = register(new BlockItem("mangrove_button", builder()));
- public static final Item BAMBOO_BUTTON = register(new BlockItem("bamboo_button", builder()));
- public static final Item CRIMSON_BUTTON = register(new BlockItem("crimson_button", builder()));
- public static final Item WARPED_BUTTON = register(new BlockItem("warped_button", builder()));
- public static final Item STONE_PRESSURE_PLATE = register(new BlockItem("stone_pressure_plate", builder()));
- public static final Item POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new BlockItem("polished_blackstone_pressure_plate", builder()));
- public static final Item LIGHT_WEIGHTED_PRESSURE_PLATE = register(new BlockItem("light_weighted_pressure_plate", builder()));
- public static final Item HEAVY_WEIGHTED_PRESSURE_PLATE = register(new BlockItem("heavy_weighted_pressure_plate", builder()));
- public static final Item OAK_PRESSURE_PLATE = register(new BlockItem("oak_pressure_plate", builder()));
- public static final Item SPRUCE_PRESSURE_PLATE = register(new BlockItem("spruce_pressure_plate", builder()));
- public static final Item BIRCH_PRESSURE_PLATE = register(new BlockItem("birch_pressure_plate", builder()));
- public static final Item JUNGLE_PRESSURE_PLATE = register(new BlockItem("jungle_pressure_plate", builder()));
- public static final Item ACACIA_PRESSURE_PLATE = register(new BlockItem("acacia_pressure_plate", builder()));
- public static final Item CHERRY_PRESSURE_PLATE = register(new BlockItem("cherry_pressure_plate", builder()));
- public static final Item DARK_OAK_PRESSURE_PLATE = register(new BlockItem("dark_oak_pressure_plate", builder()));
- public static final Item MANGROVE_PRESSURE_PLATE = register(new BlockItem("mangrove_pressure_plate", builder()));
- public static final Item BAMBOO_PRESSURE_PLATE = register(new BlockItem("bamboo_pressure_plate", builder()));
- public static final Item CRIMSON_PRESSURE_PLATE = register(new BlockItem("crimson_pressure_plate", builder()));
- public static final Item WARPED_PRESSURE_PLATE = register(new BlockItem("warped_pressure_plate", builder()));
- public static final Item IRON_DOOR = register(new BlockItem("iron_door", builder()));
- public static final Item OAK_DOOR = register(new BlockItem("oak_door", builder()));
- public static final Item SPRUCE_DOOR = register(new BlockItem("spruce_door", builder()));
- public static final Item BIRCH_DOOR = register(new BlockItem("birch_door", builder()));
- public static final Item JUNGLE_DOOR = register(new BlockItem("jungle_door", builder()));
- public static final Item ACACIA_DOOR = register(new BlockItem("acacia_door", builder()));
- public static final Item CHERRY_DOOR = register(new BlockItem("cherry_door", builder()));
- public static final Item DARK_OAK_DOOR = register(new BlockItem("dark_oak_door", builder()));
- public static final Item MANGROVE_DOOR = register(new BlockItem("mangrove_door", builder()));
- public static final Item BAMBOO_DOOR = register(new BlockItem("bamboo_door", builder()));
- public static final Item CRIMSON_DOOR = register(new BlockItem("crimson_door", builder()));
- public static final Item WARPED_DOOR = register(new BlockItem("warped_door", builder()));
- public static final Item COPPER_DOOR = register(new BlockItem("copper_door", builder()));
- public static final Item EXPOSED_COPPER_DOOR = register(new BlockItem("exposed_copper_door", builder()));
- public static final Item WEATHERED_COPPER_DOOR = register(new BlockItem("weathered_copper_door", builder()));
- public static final Item OXIDIZED_COPPER_DOOR = register(new BlockItem("oxidized_copper_door", builder()));
- public static final Item WAXED_COPPER_DOOR = register(new BlockItem("waxed_copper_door", builder()));
- public static final Item WAXED_EXPOSED_COPPER_DOOR = register(new BlockItem("waxed_exposed_copper_door", builder()));
- public static final Item WAXED_WEATHERED_COPPER_DOOR = register(new BlockItem("waxed_weathered_copper_door", builder()));
- public static final Item WAXED_OXIDIZED_COPPER_DOOR = register(new BlockItem("waxed_oxidized_copper_door", builder()));
- public static final Item IRON_TRAPDOOR = register(new BlockItem("iron_trapdoor", builder()));
- public static final Item OAK_TRAPDOOR = register(new BlockItem("oak_trapdoor", builder()));
- public static final Item SPRUCE_TRAPDOOR = register(new BlockItem("spruce_trapdoor", builder()));
- public static final Item BIRCH_TRAPDOOR = register(new BlockItem("birch_trapdoor", builder()));
- public static final Item JUNGLE_TRAPDOOR = register(new BlockItem("jungle_trapdoor", builder()));
- public static final Item ACACIA_TRAPDOOR = register(new BlockItem("acacia_trapdoor", builder()));
- public static final Item CHERRY_TRAPDOOR = register(new BlockItem("cherry_trapdoor", builder()));
- public static final Item DARK_OAK_TRAPDOOR = register(new BlockItem("dark_oak_trapdoor", builder()));
- public static final Item MANGROVE_TRAPDOOR = register(new BlockItem("mangrove_trapdoor", builder()));
- public static final Item BAMBOO_TRAPDOOR = register(new BlockItem("bamboo_trapdoor", builder()));
- public static final Item CRIMSON_TRAPDOOR = register(new BlockItem("crimson_trapdoor", builder()));
- public static final Item WARPED_TRAPDOOR = register(new BlockItem("warped_trapdoor", builder()));
- public static final Item COPPER_TRAPDOOR = register(new BlockItem("copper_trapdoor", builder()));
- public static final Item EXPOSED_COPPER_TRAPDOOR = register(new BlockItem("exposed_copper_trapdoor", builder()));
- public static final Item WEATHERED_COPPER_TRAPDOOR = register(new BlockItem("weathered_copper_trapdoor", builder()));
- public static final Item OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem("oxidized_copper_trapdoor", builder()));
- public static final Item WAXED_COPPER_TRAPDOOR = register(new BlockItem("waxed_copper_trapdoor", builder()));
- public static final Item WAXED_EXPOSED_COPPER_TRAPDOOR = register(new BlockItem("waxed_exposed_copper_trapdoor", builder()));
- public static final Item WAXED_WEATHERED_COPPER_TRAPDOOR = register(new BlockItem("waxed_weathered_copper_trapdoor", builder()));
- public static final Item WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem("waxed_oxidized_copper_trapdoor", builder()));
- public static final Item OAK_FENCE_GATE = register(new BlockItem("oak_fence_gate", builder()));
- public static final Item SPRUCE_FENCE_GATE = register(new BlockItem("spruce_fence_gate", builder()));
- public static final Item BIRCH_FENCE_GATE = register(new BlockItem("birch_fence_gate", builder()));
- public static final Item JUNGLE_FENCE_GATE = register(new BlockItem("jungle_fence_gate", builder()));
- public static final Item ACACIA_FENCE_GATE = register(new BlockItem("acacia_fence_gate", builder()));
- public static final Item CHERRY_FENCE_GATE = register(new BlockItem("cherry_fence_gate", builder()));
- public static final Item DARK_OAK_FENCE_GATE = register(new BlockItem("dark_oak_fence_gate", builder()));
- public static final Item MANGROVE_FENCE_GATE = register(new BlockItem("mangrove_fence_gate", builder()));
- public static final Item BAMBOO_FENCE_GATE = register(new BlockItem("bamboo_fence_gate", builder()));
- public static final Item CRIMSON_FENCE_GATE = register(new BlockItem("crimson_fence_gate", builder()));
- public static final Item WARPED_FENCE_GATE = register(new BlockItem("warped_fence_gate", builder()));
- public static final Item POWERED_RAIL = register(new BlockItem("powered_rail", builder()));
- public static final Item DETECTOR_RAIL = register(new BlockItem("detector_rail", builder()));
- public static final Item RAIL = register(new BlockItem("rail", builder()));
- public static final Item ACTIVATOR_RAIL = register(new BlockItem("activator_rail", builder()));
+ public static final Item STONE = register(new BlockItem(builder(), Blocks.STONE));
+ public static final Item GRANITE = register(new BlockItem(builder(), Blocks.GRANITE));
+ public static final Item POLISHED_GRANITE = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE));
+ public static final Item DIORITE = register(new BlockItem(builder(), Blocks.DIORITE));
+ public static final Item POLISHED_DIORITE = register(new BlockItem(builder(), Blocks.POLISHED_DIORITE));
+ public static final Item ANDESITE = register(new BlockItem(builder(), Blocks.ANDESITE));
+ public static final Item POLISHED_ANDESITE = register(new BlockItem(builder(), Blocks.POLISHED_ANDESITE));
+ public static final Item DEEPSLATE = register(new BlockItem(builder(), Blocks.DEEPSLATE));
+ public static final Item COBBLED_DEEPSLATE = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE));
+ public static final Item POLISHED_DEEPSLATE = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE));
+ public static final Item CALCITE = register(new BlockItem(builder(), Blocks.CALCITE));
+ public static final Item TUFF = register(new BlockItem(builder(), Blocks.TUFF));
+ public static final Item TUFF_SLAB = register(new BlockItem(builder(), Blocks.TUFF_SLAB));
+ public static final Item TUFF_STAIRS = register(new BlockItem(builder(), Blocks.TUFF_STAIRS));
+ public static final Item TUFF_WALL = register(new BlockItem(builder(), Blocks.TUFF_WALL));
+ public static final Item CHISELED_TUFF = register(new BlockItem(builder(), Blocks.CHISELED_TUFF));
+ public static final Item POLISHED_TUFF = register(new BlockItem(builder(), Blocks.POLISHED_TUFF));
+ public static final Item POLISHED_TUFF_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_TUFF_SLAB));
+ public static final Item POLISHED_TUFF_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_TUFF_STAIRS));
+ public static final Item POLISHED_TUFF_WALL = register(new BlockItem(builder(), Blocks.POLISHED_TUFF_WALL));
+ public static final Item TUFF_BRICKS = register(new BlockItem(builder(), Blocks.TUFF_BRICKS));
+ public static final Item TUFF_BRICK_SLAB = register(new BlockItem(builder(), Blocks.TUFF_BRICK_SLAB));
+ public static final Item TUFF_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.TUFF_BRICK_STAIRS));
+ public static final Item TUFF_BRICK_WALL = register(new BlockItem(builder(), Blocks.TUFF_BRICK_WALL));
+ public static final Item CHISELED_TUFF_BRICKS = register(new BlockItem(builder(), Blocks.CHISELED_TUFF_BRICKS));
+ public static final Item DRIPSTONE_BLOCK = register(new BlockItem(builder(), Blocks.DRIPSTONE_BLOCK));
+ public static final Item GRASS_BLOCK = register(new BlockItem(builder(), Blocks.GRASS_BLOCK));
+ public static final Item DIRT = register(new BlockItem(builder(), Blocks.DIRT));
+ public static final Item COARSE_DIRT = register(new BlockItem(builder(), Blocks.COARSE_DIRT));
+ public static final Item PODZOL = register(new BlockItem(builder(), Blocks.PODZOL));
+ public static final Item ROOTED_DIRT = register(new BlockItem(builder(), Blocks.ROOTED_DIRT));
+ public static final Item MUD = register(new BlockItem(builder(), Blocks.MUD));
+ public static final Item CRIMSON_NYLIUM = register(new BlockItem(builder(), Blocks.CRIMSON_NYLIUM));
+ public static final Item WARPED_NYLIUM = register(new BlockItem(builder(), Blocks.WARPED_NYLIUM));
+ public static final Item COBBLESTONE = register(new BlockItem(builder(), Blocks.COBBLESTONE));
+ public static final Item OAK_PLANKS = register(new BlockItem(builder(), Blocks.OAK_PLANKS));
+ public static final Item SPRUCE_PLANKS = register(new BlockItem(builder(), Blocks.SPRUCE_PLANKS));
+ public static final Item BIRCH_PLANKS = register(new BlockItem(builder(), Blocks.BIRCH_PLANKS));
+ public static final Item JUNGLE_PLANKS = register(new BlockItem(builder(), Blocks.JUNGLE_PLANKS));
+ public static final Item ACACIA_PLANKS = register(new BlockItem(builder(), Blocks.ACACIA_PLANKS));
+ public static final Item CHERRY_PLANKS = register(new BlockItem(builder(), Blocks.CHERRY_PLANKS));
+ public static final Item DARK_OAK_PLANKS = register(new BlockItem(builder(), Blocks.DARK_OAK_PLANKS));
+ public static final Item MANGROVE_PLANKS = register(new BlockItem(builder(), Blocks.MANGROVE_PLANKS));
+ public static final Item BAMBOO_PLANKS = register(new BlockItem(builder(), Blocks.BAMBOO_PLANKS));
+ public static final Item CRIMSON_PLANKS = register(new BlockItem(builder(), Blocks.CRIMSON_PLANKS));
+ public static final Item WARPED_PLANKS = register(new BlockItem(builder(), Blocks.WARPED_PLANKS));
+ public static final Item BAMBOO_MOSAIC = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC));
+ public static final Item OAK_SAPLING = register(new BlockItem(builder(), Blocks.OAK_SAPLING));
+ public static final Item SPRUCE_SAPLING = register(new BlockItem(builder(), Blocks.SPRUCE_SAPLING));
+ public static final Item BIRCH_SAPLING = register(new BlockItem(builder(), Blocks.BIRCH_SAPLING));
+ public static final Item JUNGLE_SAPLING = register(new BlockItem(builder(), Blocks.JUNGLE_SAPLING));
+ public static final Item ACACIA_SAPLING = register(new BlockItem(builder(), Blocks.ACACIA_SAPLING));
+ public static final Item CHERRY_SAPLING = register(new BlockItem(builder(), Blocks.CHERRY_SAPLING));
+ public static final Item DARK_OAK_SAPLING = register(new BlockItem(builder(), Blocks.DARK_OAK_SAPLING));
+ public static final Item MANGROVE_PROPAGULE = register(new BlockItem(builder(), Blocks.MANGROVE_PROPAGULE));
+ public static final Item BEDROCK = register(new BlockItem(builder(), Blocks.BEDROCK));
+ public static final Item SAND = register(new BlockItem(builder(), Blocks.SAND));
+ public static final Item SUSPICIOUS_SAND = register(new BlockItem(builder(), Blocks.SUSPICIOUS_SAND));
+ public static final Item SUSPICIOUS_GRAVEL = register(new BlockItem(builder(), Blocks.SUSPICIOUS_GRAVEL));
+ public static final Item RED_SAND = register(new BlockItem(builder(), Blocks.RED_SAND));
+ public static final Item GRAVEL = register(new BlockItem(builder(), Blocks.GRAVEL));
+ public static final Item COAL_ORE = register(new BlockItem(builder(), Blocks.COAL_ORE));
+ public static final Item DEEPSLATE_COAL_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_COAL_ORE));
+ public static final Item IRON_ORE = register(new BlockItem(builder(), Blocks.IRON_ORE));
+ public static final Item DEEPSLATE_IRON_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_IRON_ORE));
+ public static final Item COPPER_ORE = register(new BlockItem(builder(), Blocks.COPPER_ORE));
+ public static final Item DEEPSLATE_COPPER_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_COPPER_ORE));
+ public static final Item GOLD_ORE = register(new BlockItem(builder(), Blocks.GOLD_ORE));
+ public static final Item DEEPSLATE_GOLD_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_GOLD_ORE));
+ public static final Item REDSTONE_ORE = register(new BlockItem(builder(), Blocks.REDSTONE_ORE));
+ public static final Item DEEPSLATE_REDSTONE_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_REDSTONE_ORE));
+ public static final Item EMERALD_ORE = register(new BlockItem(builder(), Blocks.EMERALD_ORE));
+ public static final Item DEEPSLATE_EMERALD_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_EMERALD_ORE));
+ public static final Item LAPIS_ORE = register(new BlockItem(builder(), Blocks.LAPIS_ORE));
+ public static final Item DEEPSLATE_LAPIS_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_LAPIS_ORE));
+ public static final Item DIAMOND_ORE = register(new BlockItem(builder(), Blocks.DIAMOND_ORE));
+ public static final Item DEEPSLATE_DIAMOND_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_DIAMOND_ORE));
+ public static final Item NETHER_GOLD_ORE = register(new BlockItem(builder(), Blocks.NETHER_GOLD_ORE));
+ public static final Item NETHER_QUARTZ_ORE = register(new BlockItem(builder(), Blocks.NETHER_QUARTZ_ORE));
+ public static final Item ANCIENT_DEBRIS = register(new BlockItem(builder(), Blocks.ANCIENT_DEBRIS));
+ public static final Item COAL_BLOCK = register(new BlockItem(builder(), Blocks.COAL_BLOCK));
+ public static final Item RAW_IRON_BLOCK = register(new BlockItem(builder(), Blocks.RAW_IRON_BLOCK));
+ public static final Item RAW_COPPER_BLOCK = register(new BlockItem(builder(), Blocks.RAW_COPPER_BLOCK));
+ public static final Item RAW_GOLD_BLOCK = register(new BlockItem(builder(), Blocks.RAW_GOLD_BLOCK));
+ public static final Item HEAVY_CORE = register(new BlockItem(builder(), Blocks.HEAVY_CORE));
+ public static final Item AMETHYST_BLOCK = register(new BlockItem(builder(), Blocks.AMETHYST_BLOCK));
+ public static final Item BUDDING_AMETHYST = register(new BlockItem(builder(), Blocks.BUDDING_AMETHYST));
+ public static final Item IRON_BLOCK = register(new BlockItem(builder(), Blocks.IRON_BLOCK));
+ public static final Item COPPER_BLOCK = register(new BlockItem(builder(), Blocks.COPPER_BLOCK));
+ public static final Item GOLD_BLOCK = register(new BlockItem(builder(), Blocks.GOLD_BLOCK));
+ public static final Item DIAMOND_BLOCK = register(new BlockItem(builder(), Blocks.DIAMOND_BLOCK));
+ public static final Item NETHERITE_BLOCK = register(new BlockItem(builder(), Blocks.NETHERITE_BLOCK));
+ public static final Item EXPOSED_COPPER = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER));
+ public static final Item WEATHERED_COPPER = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER));
+ public static final Item OXIDIZED_COPPER = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER));
+ public static final Item CHISELED_COPPER = register(new BlockItem(builder(), Blocks.CHISELED_COPPER));
+ public static final Item EXPOSED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.EXPOSED_CHISELED_COPPER));
+ public static final Item WEATHERED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WEATHERED_CHISELED_COPPER));
+ public static final Item OXIDIZED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.OXIDIZED_CHISELED_COPPER));
+ public static final Item CUT_COPPER = register(new BlockItem(builder(), Blocks.CUT_COPPER));
+ public static final Item EXPOSED_CUT_COPPER = register(new BlockItem(builder(), Blocks.EXPOSED_CUT_COPPER));
+ public static final Item WEATHERED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WEATHERED_CUT_COPPER));
+ public static final Item OXIDIZED_CUT_COPPER = register(new BlockItem(builder(), Blocks.OXIDIZED_CUT_COPPER));
+ public static final Item CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.CUT_COPPER_STAIRS));
+ public static final Item EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.EXPOSED_CUT_COPPER_STAIRS));
+ public static final Item WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WEATHERED_CUT_COPPER_STAIRS));
+ public static final Item OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.OXIDIZED_CUT_COPPER_STAIRS));
+ public static final Item CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.CUT_COPPER_SLAB));
+ public static final Item EXPOSED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.EXPOSED_CUT_COPPER_SLAB));
+ public static final Item WEATHERED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WEATHERED_CUT_COPPER_SLAB));
+ public static final Item OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.OXIDIZED_CUT_COPPER_SLAB));
+ public static final Item WAXED_COPPER_BLOCK = register(new BlockItem(builder(), Blocks.WAXED_COPPER_BLOCK));
+ public static final Item WAXED_EXPOSED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER));
+ public static final Item WAXED_WEATHERED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER));
+ public static final Item WAXED_OXIDIZED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER));
+ public static final Item WAXED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_CHISELED_COPPER));
+ public static final Item WAXED_EXPOSED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CHISELED_COPPER));
+ public static final Item WAXED_WEATHERED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CHISELED_COPPER));
+ public static final Item WAXED_OXIDIZED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CHISELED_COPPER));
+ public static final Item WAXED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_CUT_COPPER));
+ public static final Item WAXED_EXPOSED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CUT_COPPER));
+ public static final Item WAXED_WEATHERED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CUT_COPPER));
+ public static final Item WAXED_OXIDIZED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CUT_COPPER));
+ public static final Item WAXED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_CUT_COPPER_STAIRS));
+ public static final Item WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CUT_COPPER_STAIRS));
+ public static final Item WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CUT_COPPER_STAIRS));
+ public static final Item WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CUT_COPPER_STAIRS));
+ public static final Item WAXED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_CUT_COPPER_SLAB));
+ public static final Item WAXED_EXPOSED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CUT_COPPER_SLAB));
+ public static final Item WAXED_WEATHERED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CUT_COPPER_SLAB));
+ public static final Item WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CUT_COPPER_SLAB));
+ public static final Item OAK_LOG = register(new BlockItem(builder(), Blocks.OAK_LOG));
+ public static final Item SPRUCE_LOG = register(new BlockItem(builder(), Blocks.SPRUCE_LOG));
+ public static final Item BIRCH_LOG = register(new BlockItem(builder(), Blocks.BIRCH_LOG));
+ public static final Item JUNGLE_LOG = register(new BlockItem(builder(), Blocks.JUNGLE_LOG));
+ public static final Item ACACIA_LOG = register(new BlockItem(builder(), Blocks.ACACIA_LOG));
+ public static final Item CHERRY_LOG = register(new BlockItem(builder(), Blocks.CHERRY_LOG));
+ public static final Item DARK_OAK_LOG = register(new BlockItem(builder(), Blocks.DARK_OAK_LOG));
+ public static final Item MANGROVE_LOG = register(new BlockItem(builder(), Blocks.MANGROVE_LOG));
+ public static final Item MANGROVE_ROOTS = register(new BlockItem(builder(), Blocks.MANGROVE_ROOTS));
+ public static final Item MUDDY_MANGROVE_ROOTS = register(new BlockItem(builder(), Blocks.MUDDY_MANGROVE_ROOTS));
+ public static final Item CRIMSON_STEM = register(new BlockItem(builder(), Blocks.CRIMSON_STEM));
+ public static final Item WARPED_STEM = register(new BlockItem(builder(), Blocks.WARPED_STEM));
+ public static final Item BAMBOO_BLOCK = register(new BlockItem(builder(), Blocks.BAMBOO_BLOCK));
+ public static final Item STRIPPED_OAK_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_OAK_LOG));
+ public static final Item STRIPPED_SPRUCE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_SPRUCE_LOG));
+ public static final Item STRIPPED_BIRCH_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_BIRCH_LOG));
+ public static final Item STRIPPED_JUNGLE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_JUNGLE_LOG));
+ public static final Item STRIPPED_ACACIA_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_ACACIA_LOG));
+ public static final Item STRIPPED_CHERRY_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_CHERRY_LOG));
+ public static final Item STRIPPED_DARK_OAK_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_DARK_OAK_LOG));
+ public static final Item STRIPPED_MANGROVE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_MANGROVE_LOG));
+ public static final Item STRIPPED_CRIMSON_STEM = register(new BlockItem(builder(), Blocks.STRIPPED_CRIMSON_STEM));
+ public static final Item STRIPPED_WARPED_STEM = register(new BlockItem(builder(), Blocks.STRIPPED_WARPED_STEM));
+ public static final Item STRIPPED_OAK_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_OAK_WOOD));
+ public static final Item STRIPPED_SPRUCE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_SPRUCE_WOOD));
+ public static final Item STRIPPED_BIRCH_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_BIRCH_WOOD));
+ public static final Item STRIPPED_JUNGLE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_JUNGLE_WOOD));
+ public static final Item STRIPPED_ACACIA_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_ACACIA_WOOD));
+ public static final Item STRIPPED_CHERRY_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_CHERRY_WOOD));
+ public static final Item STRIPPED_DARK_OAK_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_DARK_OAK_WOOD));
+ public static final Item STRIPPED_MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_MANGROVE_WOOD));
+ public static final Item STRIPPED_CRIMSON_HYPHAE = register(new BlockItem(builder(), Blocks.STRIPPED_CRIMSON_HYPHAE));
+ public static final Item STRIPPED_WARPED_HYPHAE = register(new BlockItem(builder(), Blocks.STRIPPED_WARPED_HYPHAE));
+ public static final Item STRIPPED_BAMBOO_BLOCK = register(new BlockItem(builder(), Blocks.STRIPPED_BAMBOO_BLOCK));
+ public static final Item OAK_WOOD = register(new BlockItem(builder(), Blocks.OAK_WOOD));
+ public static final Item SPRUCE_WOOD = register(new BlockItem(builder(), Blocks.SPRUCE_WOOD));
+ public static final Item BIRCH_WOOD = register(new BlockItem(builder(), Blocks.BIRCH_WOOD));
+ public static final Item JUNGLE_WOOD = register(new BlockItem(builder(), Blocks.JUNGLE_WOOD));
+ public static final Item ACACIA_WOOD = register(new BlockItem(builder(), Blocks.ACACIA_WOOD));
+ public static final Item CHERRY_WOOD = register(new BlockItem(builder(), Blocks.CHERRY_WOOD));
+ public static final Item DARK_OAK_WOOD = register(new BlockItem(builder(), Blocks.DARK_OAK_WOOD));
+ public static final Item MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.MANGROVE_WOOD));
+ public static final Item CRIMSON_HYPHAE = register(new BlockItem(builder(), Blocks.CRIMSON_HYPHAE));
+ public static final Item WARPED_HYPHAE = register(new BlockItem(builder(), Blocks.WARPED_HYPHAE));
+ public static final Item OAK_LEAVES = register(new BlockItem(builder(), Blocks.OAK_LEAVES));
+ public static final Item SPRUCE_LEAVES = register(new BlockItem(builder(), Blocks.SPRUCE_LEAVES));
+ public static final Item BIRCH_LEAVES = register(new BlockItem(builder(), Blocks.BIRCH_LEAVES));
+ public static final Item JUNGLE_LEAVES = register(new BlockItem(builder(), Blocks.JUNGLE_LEAVES));
+ public static final Item ACACIA_LEAVES = register(new BlockItem(builder(), Blocks.ACACIA_LEAVES));
+ public static final Item CHERRY_LEAVES = register(new BlockItem(builder(), Blocks.CHERRY_LEAVES));
+ public static final Item DARK_OAK_LEAVES = register(new BlockItem(builder(), Blocks.DARK_OAK_LEAVES));
+ public static final Item MANGROVE_LEAVES = register(new BlockItem(builder(), Blocks.MANGROVE_LEAVES));
+ public static final Item AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.AZALEA_LEAVES));
+ public static final Item FLOWERING_AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.FLOWERING_AZALEA_LEAVES));
+ public static final Item SPONGE = register(new BlockItem(builder(), Blocks.SPONGE));
+ public static final Item WET_SPONGE = register(new BlockItem(builder(), Blocks.WET_SPONGE));
+ public static final Item GLASS = register(new BlockItem(builder(), Blocks.GLASS));
+ public static final Item TINTED_GLASS = register(new BlockItem(builder(), Blocks.TINTED_GLASS));
+ public static final Item LAPIS_BLOCK = register(new BlockItem(builder(), Blocks.LAPIS_BLOCK));
+ public static final Item SANDSTONE = register(new BlockItem(builder(), Blocks.SANDSTONE));
+ public static final Item CHISELED_SANDSTONE = register(new BlockItem(builder(), Blocks.CHISELED_SANDSTONE));
+ public static final Item CUT_SANDSTONE = register(new BlockItem(builder(), Blocks.CUT_SANDSTONE));
+ public static final Item COBWEB = register(new BlockItem(builder(), Blocks.COBWEB));
+ public static final Item SHORT_GRASS = register(new BlockItem(builder(), Blocks.SHORT_GRASS));
+ public static final Item FERN = register(new BlockItem(builder(), Blocks.FERN));
+ public static final Item AZALEA = register(new BlockItem(builder(), Blocks.AZALEA));
+ public static final Item FLOWERING_AZALEA = register(new BlockItem(builder(), Blocks.FLOWERING_AZALEA));
+ public static final Item DEAD_BUSH = register(new BlockItem(builder(), Blocks.DEAD_BUSH));
+ public static final Item SEAGRASS = register(new BlockItem(builder(), Blocks.SEAGRASS));
+ public static final Item SEA_PICKLE = register(new BlockItem(builder(), Blocks.SEA_PICKLE));
+ public static final Item WHITE_WOOL = register(new BlockItem(builder(), Blocks.WHITE_WOOL));
+ public static final Item ORANGE_WOOL = register(new BlockItem(builder(), Blocks.ORANGE_WOOL));
+ public static final Item MAGENTA_WOOL = register(new BlockItem(builder(), Blocks.MAGENTA_WOOL));
+ public static final Item LIGHT_BLUE_WOOL = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_WOOL));
+ public static final Item YELLOW_WOOL = register(new BlockItem(builder(), Blocks.YELLOW_WOOL));
+ public static final Item LIME_WOOL = register(new BlockItem(builder(), Blocks.LIME_WOOL));
+ public static final Item PINK_WOOL = register(new BlockItem(builder(), Blocks.PINK_WOOL));
+ public static final Item GRAY_WOOL = register(new BlockItem(builder(), Blocks.GRAY_WOOL));
+ public static final Item LIGHT_GRAY_WOOL = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_WOOL));
+ public static final Item CYAN_WOOL = register(new BlockItem(builder(), Blocks.CYAN_WOOL));
+ public static final Item PURPLE_WOOL = register(new BlockItem(builder(), Blocks.PURPLE_WOOL));
+ public static final Item BLUE_WOOL = register(new BlockItem(builder(), Blocks.BLUE_WOOL));
+ public static final Item BROWN_WOOL = register(new BlockItem(builder(), Blocks.BROWN_WOOL));
+ public static final Item GREEN_WOOL = register(new BlockItem(builder(), Blocks.GREEN_WOOL));
+ public static final Item RED_WOOL = register(new BlockItem(builder(), Blocks.RED_WOOL));
+ public static final Item BLACK_WOOL = register(new BlockItem(builder(), Blocks.BLACK_WOOL));
+ public static final Item DANDELION = register(new BlockItem(builder(), Blocks.DANDELION));
+ public static final Item POPPY = register(new BlockItem(builder(), Blocks.POPPY));
+ public static final Item BLUE_ORCHID = register(new BlockItem(builder(), Blocks.BLUE_ORCHID));
+ public static final Item ALLIUM = register(new BlockItem(builder(), Blocks.ALLIUM));
+ public static final Item AZURE_BLUET = register(new BlockItem(builder(), Blocks.AZURE_BLUET));
+ public static final Item RED_TULIP = register(new BlockItem(builder(), Blocks.RED_TULIP));
+ public static final Item ORANGE_TULIP = register(new BlockItem(builder(), Blocks.ORANGE_TULIP));
+ public static final Item WHITE_TULIP = register(new BlockItem(builder(), Blocks.WHITE_TULIP));
+ public static final Item PINK_TULIP = register(new BlockItem(builder(), Blocks.PINK_TULIP));
+ public static final Item OXEYE_DAISY = register(new BlockItem(builder(), Blocks.OXEYE_DAISY));
+ public static final Item CORNFLOWER = register(new BlockItem(builder(), Blocks.CORNFLOWER));
+ public static final Item LILY_OF_THE_VALLEY = register(new BlockItem(builder(), Blocks.LILY_OF_THE_VALLEY));
+ public static final Item WITHER_ROSE = register(new BlockItem(builder(), Blocks.WITHER_ROSE));
+ public static final Item TORCHFLOWER = register(new BlockItem(builder(), Blocks.TORCHFLOWER));
+ public static final Item PITCHER_PLANT = register(new BlockItem(builder(), Blocks.PITCHER_PLANT));
+ public static final Item SPORE_BLOSSOM = register(new BlockItem(builder(), Blocks.SPORE_BLOSSOM));
+ public static final Item BROWN_MUSHROOM = register(new BlockItem(builder(), Blocks.BROWN_MUSHROOM));
+ public static final Item RED_MUSHROOM = register(new BlockItem(builder(), Blocks.RED_MUSHROOM));
+ public static final Item CRIMSON_FUNGUS = register(new BlockItem(builder(), Blocks.CRIMSON_FUNGUS));
+ public static final Item WARPED_FUNGUS = register(new BlockItem(builder(), Blocks.WARPED_FUNGUS));
+ public static final Item CRIMSON_ROOTS = register(new BlockItem(builder(), Blocks.CRIMSON_ROOTS));
+ public static final Item WARPED_ROOTS = register(new BlockItem(builder(), Blocks.WARPED_ROOTS));
+ public static final Item NETHER_SPROUTS = register(new BlockItem(builder(), Blocks.NETHER_SPROUTS));
+ public static final Item WEEPING_VINES = register(new BlockItem(builder(), Blocks.WEEPING_VINES));
+ public static final Item TWISTING_VINES = register(new BlockItem(builder(), Blocks.TWISTING_VINES));
+ public static final Item SUGAR_CANE = register(new BlockItem(builder(), Blocks.SUGAR_CANE));
+ public static final Item KELP = register(new BlockItem(builder(), Blocks.KELP));
+ public static final Item MOSS_CARPET = register(new BlockItem(builder(), Blocks.MOSS_CARPET));
+ public static final Item PINK_PETALS = register(new BlockItem(builder(), Blocks.PINK_PETALS));
+ public static final Item MOSS_BLOCK = register(new BlockItem(builder(), Blocks.MOSS_BLOCK));
+ public static final Item HANGING_ROOTS = register(new BlockItem(builder(), Blocks.HANGING_ROOTS));
+ public static final Item BIG_DRIPLEAF = register(new BlockItem(builder(), Blocks.BIG_DRIPLEAF, Blocks.BIG_DRIPLEAF_STEM));
+ public static final Item SMALL_DRIPLEAF = register(new BlockItem(builder(), Blocks.SMALL_DRIPLEAF));
+ public static final Item BAMBOO = register(new BlockItem(builder(), Blocks.BAMBOO));
+ public static final Item OAK_SLAB = register(new BlockItem(builder(), Blocks.OAK_SLAB));
+ public static final Item SPRUCE_SLAB = register(new BlockItem(builder(), Blocks.SPRUCE_SLAB));
+ public static final Item BIRCH_SLAB = register(new BlockItem(builder(), Blocks.BIRCH_SLAB));
+ public static final Item JUNGLE_SLAB = register(new BlockItem(builder(), Blocks.JUNGLE_SLAB));
+ public static final Item ACACIA_SLAB = register(new BlockItem(builder(), Blocks.ACACIA_SLAB));
+ public static final Item CHERRY_SLAB = register(new BlockItem(builder(), Blocks.CHERRY_SLAB));
+ public static final Item DARK_OAK_SLAB = register(new BlockItem(builder(), Blocks.DARK_OAK_SLAB));
+ public static final Item MANGROVE_SLAB = register(new BlockItem(builder(), Blocks.MANGROVE_SLAB));
+ public static final Item BAMBOO_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_SLAB));
+ public static final Item BAMBOO_MOSAIC_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_SLAB));
+ public static final Item CRIMSON_SLAB = register(new BlockItem(builder(), Blocks.CRIMSON_SLAB));
+ public static final Item WARPED_SLAB = register(new BlockItem(builder(), Blocks.WARPED_SLAB));
+ public static final Item STONE_SLAB = register(new BlockItem(builder(), Blocks.STONE_SLAB));
+ public static final Item SMOOTH_STONE_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_STONE_SLAB));
+ public static final Item SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.SANDSTONE_SLAB));
+ public static final Item CUT_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.CUT_SANDSTONE_SLAB));
+ public static final Item PETRIFIED_OAK_SLAB = register(new BlockItem(builder(), Blocks.PETRIFIED_OAK_SLAB));
+ public static final Item COBBLESTONE_SLAB = register(new BlockItem(builder(), Blocks.COBBLESTONE_SLAB));
+ public static final Item BRICK_SLAB = register(new BlockItem(builder(), Blocks.BRICK_SLAB));
+ public static final Item STONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.STONE_BRICK_SLAB));
+ public static final Item MUD_BRICK_SLAB = register(new BlockItem(builder(), Blocks.MUD_BRICK_SLAB));
+ public static final Item NETHER_BRICK_SLAB = register(new BlockItem(builder(), Blocks.NETHER_BRICK_SLAB));
+ public static final Item QUARTZ_SLAB = register(new BlockItem(builder(), Blocks.QUARTZ_SLAB));
+ public static final Item RED_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_SLAB));
+ public static final Item CUT_RED_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.CUT_RED_SANDSTONE_SLAB));
+ public static final Item PURPUR_SLAB = register(new BlockItem(builder(), Blocks.PURPUR_SLAB));
+ public static final Item PRISMARINE_SLAB = register(new BlockItem(builder(), Blocks.PRISMARINE_SLAB));
+ public static final Item PRISMARINE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.PRISMARINE_BRICK_SLAB));
+ public static final Item DARK_PRISMARINE_SLAB = register(new BlockItem(builder(), Blocks.DARK_PRISMARINE_SLAB));
+ public static final Item SMOOTH_QUARTZ = register(new BlockItem(builder(), Blocks.SMOOTH_QUARTZ));
+ public static final Item SMOOTH_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE));
+ public static final Item SMOOTH_SANDSTONE = register(new BlockItem(builder(), Blocks.SMOOTH_SANDSTONE));
+ public static final Item SMOOTH_STONE = register(new BlockItem(builder(), Blocks.SMOOTH_STONE));
+ public static final Item BRICKS = register(new BlockItem(builder(), Blocks.BRICKS));
+ public static final Item BOOKSHELF = register(new BlockItem(builder(), Blocks.BOOKSHELF));
+ public static final Item CHISELED_BOOKSHELF = register(new BlockItem(builder(), Blocks.CHISELED_BOOKSHELF));
+ public static final Item DECORATED_POT = register(new DecoratedPotItem(builder(), Blocks.DECORATED_POT));
+ public static final Item MOSSY_COBBLESTONE = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE));
+ public static final Item OBSIDIAN = register(new BlockItem(builder(), Blocks.OBSIDIAN));
+ public static final Item TORCH = register(new BlockItem(builder(), Blocks.TORCH, Blocks.WALL_TORCH));
+ public static final Item END_ROD = register(new BlockItem(builder(), Blocks.END_ROD));
+ public static final Item CHORUS_PLANT = register(new BlockItem(builder(), Blocks.CHORUS_PLANT));
+ public static final Item CHORUS_FLOWER = register(new BlockItem(builder(), Blocks.CHORUS_FLOWER));
+ public static final Item PURPUR_BLOCK = register(new BlockItem(builder(), Blocks.PURPUR_BLOCK));
+ public static final Item PURPUR_PILLAR = register(new BlockItem(builder(), Blocks.PURPUR_PILLAR));
+ public static final Item PURPUR_STAIRS = register(new BlockItem(builder(), Blocks.PURPUR_STAIRS));
+ public static final Item SPAWNER = register(new BlockItem(builder(), Blocks.SPAWNER));
+ public static final Item CHEST = register(new BlockItem(builder(), Blocks.CHEST));
+ public static final Item CRAFTING_TABLE = register(new BlockItem(builder(), Blocks.CRAFTING_TABLE));
+ public static final Item FARMLAND = register(new BlockItem(builder(), Blocks.FARMLAND));
+ public static final Item FURNACE = register(new BlockItem(builder(), Blocks.FURNACE));
+ public static final Item LADDER = register(new BlockItem(builder(), Blocks.LADDER));
+ public static final Item COBBLESTONE_STAIRS = register(new BlockItem(builder(), Blocks.COBBLESTONE_STAIRS));
+ public static final Item SNOW = register(new BlockItem(builder(), Blocks.SNOW));
+ public static final Item ICE = register(new BlockItem(builder(), Blocks.ICE));
+ public static final Item SNOW_BLOCK = register(new BlockItem(builder(), Blocks.SNOW_BLOCK));
+ public static final Item CACTUS = register(new BlockItem(builder(), Blocks.CACTUS));
+ public static final Item CLAY = register(new BlockItem(builder(), Blocks.CLAY));
+ public static final Item JUKEBOX = register(new BlockItem(builder(), Blocks.JUKEBOX));
+ public static final Item OAK_FENCE = register(new BlockItem(builder(), Blocks.OAK_FENCE));
+ public static final Item SPRUCE_FENCE = register(new BlockItem(builder(), Blocks.SPRUCE_FENCE));
+ public static final Item BIRCH_FENCE = register(new BlockItem(builder(), Blocks.BIRCH_FENCE));
+ public static final Item JUNGLE_FENCE = register(new BlockItem(builder(), Blocks.JUNGLE_FENCE));
+ public static final Item ACACIA_FENCE = register(new BlockItem(builder(), Blocks.ACACIA_FENCE));
+ public static final Item CHERRY_FENCE = register(new BlockItem(builder(), Blocks.CHERRY_FENCE));
+ public static final Item DARK_OAK_FENCE = register(new BlockItem(builder(), Blocks.DARK_OAK_FENCE));
+ public static final Item MANGROVE_FENCE = register(new BlockItem(builder(), Blocks.MANGROVE_FENCE));
+ public static final Item BAMBOO_FENCE = register(new BlockItem(builder(), Blocks.BAMBOO_FENCE));
+ public static final Item CRIMSON_FENCE = register(new BlockItem(builder(), Blocks.CRIMSON_FENCE));
+ public static final Item WARPED_FENCE = register(new BlockItem(builder(), Blocks.WARPED_FENCE));
+ public static final Item PUMPKIN = register(new BlockItem(builder(), Blocks.PUMPKIN));
+ public static final Item CARVED_PUMPKIN = register(new BlockItem(builder(), Blocks.CARVED_PUMPKIN));
+ public static final Item JACK_O_LANTERN = register(new BlockItem(builder(), Blocks.JACK_O_LANTERN));
+ public static final Item NETHERRACK = register(new BlockItem(builder(), Blocks.NETHERRACK));
+ public static final Item SOUL_SAND = register(new BlockItem(builder(), Blocks.SOUL_SAND));
+ public static final Item SOUL_SOIL = register(new BlockItem(builder(), Blocks.SOUL_SOIL));
+ public static final Item BASALT = register(new BlockItem(builder(), Blocks.BASALT));
+ public static final Item POLISHED_BASALT = register(new BlockItem(builder(), Blocks.POLISHED_BASALT));
+ public static final Item SMOOTH_BASALT = register(new BlockItem(builder(), Blocks.SMOOTH_BASALT));
+ public static final Item SOUL_TORCH = register(new BlockItem(builder(), Blocks.SOUL_TORCH, Blocks.SOUL_WALL_TORCH));
+ public static final Item GLOWSTONE = register(new BlockItem(builder(), Blocks.GLOWSTONE));
+ public static final Item INFESTED_STONE = register(new BlockItem(builder(), Blocks.INFESTED_STONE));
+ public static final Item INFESTED_COBBLESTONE = register(new BlockItem(builder(), Blocks.INFESTED_COBBLESTONE));
+ public static final Item INFESTED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_STONE_BRICKS));
+ public static final Item INFESTED_MOSSY_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_MOSSY_STONE_BRICKS));
+ public static final Item INFESTED_CRACKED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_CRACKED_STONE_BRICKS));
+ public static final Item INFESTED_CHISELED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_CHISELED_STONE_BRICKS));
+ public static final Item INFESTED_DEEPSLATE = register(new BlockItem(builder(), Blocks.INFESTED_DEEPSLATE));
+ public static final Item STONE_BRICKS = register(new BlockItem(builder(), Blocks.STONE_BRICKS));
+ public static final Item MOSSY_STONE_BRICKS = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICKS));
+ public static final Item CRACKED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_STONE_BRICKS));
+ public static final Item CHISELED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.CHISELED_STONE_BRICKS));
+ public static final Item PACKED_MUD = register(new BlockItem(builder(), Blocks.PACKED_MUD));
+ public static final Item MUD_BRICKS = register(new BlockItem(builder(), Blocks.MUD_BRICKS));
+ public static final Item DEEPSLATE_BRICKS = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICKS));
+ public static final Item CRACKED_DEEPSLATE_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_DEEPSLATE_BRICKS));
+ public static final Item DEEPSLATE_TILES = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILES));
+ public static final Item CRACKED_DEEPSLATE_TILES = register(new BlockItem(builder(), Blocks.CRACKED_DEEPSLATE_TILES));
+ public static final Item CHISELED_DEEPSLATE = register(new BlockItem(builder(), Blocks.CHISELED_DEEPSLATE));
+ public static final Item REINFORCED_DEEPSLATE = register(new BlockItem(builder(), Blocks.REINFORCED_DEEPSLATE));
+ public static final Item BROWN_MUSHROOM_BLOCK = register(new BlockItem(builder(), Blocks.BROWN_MUSHROOM_BLOCK));
+ public static final Item RED_MUSHROOM_BLOCK = register(new BlockItem(builder(), Blocks.RED_MUSHROOM_BLOCK));
+ public static final Item MUSHROOM_STEM = register(new BlockItem(builder(), Blocks.MUSHROOM_STEM));
+ public static final Item IRON_BARS = register(new BlockItem(builder(), Blocks.IRON_BARS));
+ public static final Item CHAIN = register(new BlockItem(builder(), Blocks.CHAIN));
+ public static final Item GLASS_PANE = register(new BlockItem(builder(), Blocks.GLASS_PANE));
+ public static final Item MELON = register(new BlockItem(builder(), Blocks.MELON));
+ public static final Item VINE = register(new BlockItem(builder(), Blocks.VINE));
+ public static final Item GLOW_LICHEN = register(new BlockItem(builder(), Blocks.GLOW_LICHEN));
+ public static final Item BRICK_STAIRS = register(new BlockItem(builder(), Blocks.BRICK_STAIRS));
+ public static final Item STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.STONE_BRICK_STAIRS));
+ public static final Item MUD_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MUD_BRICK_STAIRS));
+ public static final Item MYCELIUM = register(new BlockItem(builder(), Blocks.MYCELIUM));
+ public static final Item LILY_PAD = register(new BlockItem(builder(), Blocks.LILY_PAD));
+ public static final Item NETHER_BRICKS = register(new BlockItem(builder(), Blocks.NETHER_BRICKS));
+ public static final Item CRACKED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_NETHER_BRICKS));
+ public static final Item CHISELED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.CHISELED_NETHER_BRICKS));
+ public static final Item NETHER_BRICK_FENCE = register(new BlockItem(builder(), Blocks.NETHER_BRICK_FENCE));
+ public static final Item NETHER_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.NETHER_BRICK_STAIRS));
+ public static final Item SCULK = register(new BlockItem(builder(), Blocks.SCULK));
+ public static final Item SCULK_VEIN = register(new BlockItem(builder(), Blocks.SCULK_VEIN));
+ public static final Item SCULK_CATALYST = register(new BlockItem(builder(), Blocks.SCULK_CATALYST));
+ public static final Item SCULK_SHRIEKER = register(new BlockItem(builder(), Blocks.SCULK_SHRIEKER));
+ public static final Item ENCHANTING_TABLE = register(new BlockItem(builder(), Blocks.ENCHANTING_TABLE));
+ public static final Item END_PORTAL_FRAME = register(new BlockItem(builder(), Blocks.END_PORTAL_FRAME));
+ public static final Item END_STONE = register(new BlockItem(builder(), Blocks.END_STONE));
+ public static final Item END_STONE_BRICKS = register(new BlockItem(builder(), Blocks.END_STONE_BRICKS));
+ public static final Item DRAGON_EGG = register(new BlockItem(builder(), Blocks.DRAGON_EGG));
+ public static final Item SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SANDSTONE_STAIRS));
+ public static final Item ENDER_CHEST = register(new BlockItem(builder(), Blocks.ENDER_CHEST));
+ public static final Item EMERALD_BLOCK = register(new BlockItem(builder(), Blocks.EMERALD_BLOCK));
+ public static final Item OAK_STAIRS = register(new BlockItem(builder(), Blocks.OAK_STAIRS));
+ public static final Item SPRUCE_STAIRS = register(new BlockItem(builder(), Blocks.SPRUCE_STAIRS));
+ public static final Item BIRCH_STAIRS = register(new BlockItem(builder(), Blocks.BIRCH_STAIRS));
+ public static final Item JUNGLE_STAIRS = register(new BlockItem(builder(), Blocks.JUNGLE_STAIRS));
+ public static final Item ACACIA_STAIRS = register(new BlockItem(builder(), Blocks.ACACIA_STAIRS));
+ public static final Item CHERRY_STAIRS = register(new BlockItem(builder(), Blocks.CHERRY_STAIRS));
+ public static final Item DARK_OAK_STAIRS = register(new BlockItem(builder(), Blocks.DARK_OAK_STAIRS));
+ public static final Item MANGROVE_STAIRS = register(new BlockItem(builder(), Blocks.MANGROVE_STAIRS));
+ public static final Item BAMBOO_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_STAIRS));
+ public static final Item BAMBOO_MOSAIC_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_STAIRS));
+ public static final Item CRIMSON_STAIRS = register(new BlockItem(builder(), Blocks.CRIMSON_STAIRS));
+ public static final Item WARPED_STAIRS = register(new BlockItem(builder(), Blocks.WARPED_STAIRS));
+ public static final Item COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.COMMAND_BLOCK));
+ public static final Item BEACON = register(new BlockItem(builder(), Blocks.BEACON));
+ public static final Item COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.COBBLESTONE_WALL));
+ public static final Item MOSSY_COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_WALL));
+ public static final Item BRICK_WALL = register(new BlockItem(builder(), Blocks.BRICK_WALL));
+ public static final Item PRISMARINE_WALL = register(new BlockItem(builder(), Blocks.PRISMARINE_WALL));
+ public static final Item RED_SANDSTONE_WALL = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_WALL));
+ public static final Item MOSSY_STONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_WALL));
+ public static final Item GRANITE_WALL = register(new BlockItem(builder(), Blocks.GRANITE_WALL));
+ public static final Item STONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.STONE_BRICK_WALL));
+ public static final Item MUD_BRICK_WALL = register(new BlockItem(builder(), Blocks.MUD_BRICK_WALL));
+ public static final Item NETHER_BRICK_WALL = register(new BlockItem(builder(), Blocks.NETHER_BRICK_WALL));
+ public static final Item ANDESITE_WALL = register(new BlockItem(builder(), Blocks.ANDESITE_WALL));
+ public static final Item RED_NETHER_BRICK_WALL = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICK_WALL));
+ public static final Item SANDSTONE_WALL = register(new BlockItem(builder(), Blocks.SANDSTONE_WALL));
+ public static final Item END_STONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.END_STONE_BRICK_WALL));
+ public static final Item DIORITE_WALL = register(new BlockItem(builder(), Blocks.DIORITE_WALL));
+ public static final Item BLACKSTONE_WALL = register(new BlockItem(builder(), Blocks.BLACKSTONE_WALL));
+ public static final Item POLISHED_BLACKSTONE_WALL = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_WALL));
+ public static final Item POLISHED_BLACKSTONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICK_WALL));
+ public static final Item COBBLED_DEEPSLATE_WALL = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE_WALL));
+ public static final Item POLISHED_DEEPSLATE_WALL = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE_WALL));
+ public static final Item DEEPSLATE_BRICK_WALL = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICK_WALL));
+ public static final Item DEEPSLATE_TILE_WALL = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILE_WALL));
+ public static final Item ANVIL = register(new BlockItem(builder(), Blocks.ANVIL));
+ public static final Item CHIPPED_ANVIL = register(new BlockItem(builder(), Blocks.CHIPPED_ANVIL));
+ public static final Item DAMAGED_ANVIL = register(new BlockItem(builder(), Blocks.DAMAGED_ANVIL));
+ public static final Item CHISELED_QUARTZ_BLOCK = register(new BlockItem(builder(), Blocks.CHISELED_QUARTZ_BLOCK));
+ public static final Item QUARTZ_BLOCK = register(new BlockItem(builder(), Blocks.QUARTZ_BLOCK));
+ public static final Item QUARTZ_BRICKS = register(new BlockItem(builder(), Blocks.QUARTZ_BRICKS));
+ public static final Item QUARTZ_PILLAR = register(new BlockItem(builder(), Blocks.QUARTZ_PILLAR));
+ public static final Item QUARTZ_STAIRS = register(new BlockItem(builder(), Blocks.QUARTZ_STAIRS));
+ public static final Item WHITE_TERRACOTTA = register(new BlockItem(builder(), Blocks.WHITE_TERRACOTTA));
+ public static final Item ORANGE_TERRACOTTA = register(new BlockItem(builder(), Blocks.ORANGE_TERRACOTTA));
+ public static final Item MAGENTA_TERRACOTTA = register(new BlockItem(builder(), Blocks.MAGENTA_TERRACOTTA));
+ public static final Item LIGHT_BLUE_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_TERRACOTTA));
+ public static final Item YELLOW_TERRACOTTA = register(new BlockItem(builder(), Blocks.YELLOW_TERRACOTTA));
+ public static final Item LIME_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIME_TERRACOTTA));
+ public static final Item PINK_TERRACOTTA = register(new BlockItem(builder(), Blocks.PINK_TERRACOTTA));
+ public static final Item GRAY_TERRACOTTA = register(new BlockItem(builder(), Blocks.GRAY_TERRACOTTA));
+ public static final Item LIGHT_GRAY_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_TERRACOTTA));
+ public static final Item CYAN_TERRACOTTA = register(new BlockItem(builder(), Blocks.CYAN_TERRACOTTA));
+ public static final Item PURPLE_TERRACOTTA = register(new BlockItem(builder(), Blocks.PURPLE_TERRACOTTA));
+ public static final Item BLUE_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLUE_TERRACOTTA));
+ public static final Item BROWN_TERRACOTTA = register(new BlockItem(builder(), Blocks.BROWN_TERRACOTTA));
+ public static final Item GREEN_TERRACOTTA = register(new BlockItem(builder(), Blocks.GREEN_TERRACOTTA));
+ public static final Item RED_TERRACOTTA = register(new BlockItem(builder(), Blocks.RED_TERRACOTTA));
+ public static final Item BLACK_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLACK_TERRACOTTA));
+ public static final Item BARRIER = register(new BlockItem(builder(), Blocks.BARRIER));
+ public static final Item LIGHT = register(new BlockItem(builder(), Blocks.LIGHT));
+ public static final Item HAY_BLOCK = register(new BlockItem(builder(), Blocks.HAY_BLOCK));
+ public static final Item WHITE_CARPET = register(new BlockItem(builder(), Blocks.WHITE_CARPET));
+ public static final Item ORANGE_CARPET = register(new BlockItem(builder(), Blocks.ORANGE_CARPET));
+ public static final Item MAGENTA_CARPET = register(new BlockItem(builder(), Blocks.MAGENTA_CARPET));
+ public static final Item LIGHT_BLUE_CARPET = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CARPET));
+ public static final Item YELLOW_CARPET = register(new BlockItem(builder(), Blocks.YELLOW_CARPET));
+ public static final Item LIME_CARPET = register(new BlockItem(builder(), Blocks.LIME_CARPET));
+ public static final Item PINK_CARPET = register(new BlockItem(builder(), Blocks.PINK_CARPET));
+ public static final Item GRAY_CARPET = register(new BlockItem(builder(), Blocks.GRAY_CARPET));
+ public static final Item LIGHT_GRAY_CARPET = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CARPET));
+ public static final Item CYAN_CARPET = register(new BlockItem(builder(), Blocks.CYAN_CARPET));
+ public static final Item PURPLE_CARPET = register(new BlockItem(builder(), Blocks.PURPLE_CARPET));
+ public static final Item BLUE_CARPET = register(new BlockItem(builder(), Blocks.BLUE_CARPET));
+ public static final Item BROWN_CARPET = register(new BlockItem(builder(), Blocks.BROWN_CARPET));
+ public static final Item GREEN_CARPET = register(new BlockItem(builder(), Blocks.GREEN_CARPET));
+ public static final Item RED_CARPET = register(new BlockItem(builder(), Blocks.RED_CARPET));
+ public static final Item BLACK_CARPET = register(new BlockItem(builder(), Blocks.BLACK_CARPET));
+ public static final Item TERRACOTTA = register(new BlockItem(builder(), Blocks.TERRACOTTA));
+ public static final Item PACKED_ICE = register(new BlockItem(builder(), Blocks.PACKED_ICE));
+ public static final Item DIRT_PATH = register(new BlockItem(builder(), Blocks.DIRT_PATH));
+ public static final Item SUNFLOWER = register(new BlockItem(builder(), Blocks.SUNFLOWER));
+ public static final Item LILAC = register(new BlockItem(builder(), Blocks.LILAC));
+ public static final Item ROSE_BUSH = register(new BlockItem(builder(), Blocks.ROSE_BUSH));
+ public static final Item PEONY = register(new BlockItem(builder(), Blocks.PEONY));
+ public static final Item TALL_GRASS = register(new BlockItem(builder(), Blocks.TALL_GRASS));
+ public static final Item LARGE_FERN = register(new BlockItem(builder(), Blocks.LARGE_FERN));
+ public static final Item WHITE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.WHITE_STAINED_GLASS));
+ public static final Item ORANGE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.ORANGE_STAINED_GLASS));
+ public static final Item MAGENTA_STAINED_GLASS = register(new BlockItem(builder(), Blocks.MAGENTA_STAINED_GLASS));
+ public static final Item LIGHT_BLUE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_STAINED_GLASS));
+ public static final Item YELLOW_STAINED_GLASS = register(new BlockItem(builder(), Blocks.YELLOW_STAINED_GLASS));
+ public static final Item LIME_STAINED_GLASS = register(new BlockItem(builder(), Blocks.LIME_STAINED_GLASS));
+ public static final Item PINK_STAINED_GLASS = register(new BlockItem(builder(), Blocks.PINK_STAINED_GLASS));
+ public static final Item GRAY_STAINED_GLASS = register(new BlockItem(builder(), Blocks.GRAY_STAINED_GLASS));
+ public static final Item LIGHT_GRAY_STAINED_GLASS = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_STAINED_GLASS));
+ public static final Item CYAN_STAINED_GLASS = register(new BlockItem(builder(), Blocks.CYAN_STAINED_GLASS));
+ public static final Item PURPLE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.PURPLE_STAINED_GLASS));
+ public static final Item BLUE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.BLUE_STAINED_GLASS));
+ public static final Item BROWN_STAINED_GLASS = register(new BlockItem(builder(), Blocks.BROWN_STAINED_GLASS));
+ public static final Item GREEN_STAINED_GLASS = register(new BlockItem(builder(), Blocks.GREEN_STAINED_GLASS));
+ public static final Item RED_STAINED_GLASS = register(new BlockItem(builder(), Blocks.RED_STAINED_GLASS));
+ public static final Item BLACK_STAINED_GLASS = register(new BlockItem(builder(), Blocks.BLACK_STAINED_GLASS));
+ public static final Item WHITE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.WHITE_STAINED_GLASS_PANE));
+ public static final Item ORANGE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.ORANGE_STAINED_GLASS_PANE));
+ public static final Item MAGENTA_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.MAGENTA_STAINED_GLASS_PANE));
+ public static final Item LIGHT_BLUE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_STAINED_GLASS_PANE));
+ public static final Item YELLOW_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.YELLOW_STAINED_GLASS_PANE));
+ public static final Item LIME_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.LIME_STAINED_GLASS_PANE));
+ public static final Item PINK_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.PINK_STAINED_GLASS_PANE));
+ public static final Item GRAY_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.GRAY_STAINED_GLASS_PANE));
+ public static final Item LIGHT_GRAY_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_STAINED_GLASS_PANE));
+ public static final Item CYAN_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.CYAN_STAINED_GLASS_PANE));
+ public static final Item PURPLE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.PURPLE_STAINED_GLASS_PANE));
+ public static final Item BLUE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.BLUE_STAINED_GLASS_PANE));
+ public static final Item BROWN_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.BROWN_STAINED_GLASS_PANE));
+ public static final Item GREEN_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.GREEN_STAINED_GLASS_PANE));
+ public static final Item RED_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.RED_STAINED_GLASS_PANE));
+ public static final Item BLACK_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.BLACK_STAINED_GLASS_PANE));
+ public static final Item PRISMARINE = register(new BlockItem(builder(), Blocks.PRISMARINE));
+ public static final Item PRISMARINE_BRICKS = register(new BlockItem(builder(), Blocks.PRISMARINE_BRICKS));
+ public static final Item DARK_PRISMARINE = register(new BlockItem(builder(), Blocks.DARK_PRISMARINE));
+ public static final Item PRISMARINE_STAIRS = register(new BlockItem(builder(), Blocks.PRISMARINE_STAIRS));
+ public static final Item PRISMARINE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.PRISMARINE_BRICK_STAIRS));
+ public static final Item DARK_PRISMARINE_STAIRS = register(new BlockItem(builder(), Blocks.DARK_PRISMARINE_STAIRS));
+ public static final Item SEA_LANTERN = register(new BlockItem(builder(), Blocks.SEA_LANTERN));
+ public static final Item RED_SANDSTONE = register(new BlockItem(builder(), Blocks.RED_SANDSTONE));
+ public static final Item CHISELED_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CHISELED_RED_SANDSTONE));
+ public static final Item CUT_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CUT_RED_SANDSTONE));
+ public static final Item RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_STAIRS));
+ public static final Item REPEATING_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.REPEATING_COMMAND_BLOCK));
+ public static final Item CHAIN_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.CHAIN_COMMAND_BLOCK));
+ public static final Item MAGMA_BLOCK = register(new BlockItem(builder(), Blocks.MAGMA_BLOCK));
+ public static final Item NETHER_WART_BLOCK = register(new BlockItem(builder(), Blocks.NETHER_WART_BLOCK));
+ public static final Item WARPED_WART_BLOCK = register(new BlockItem(builder(), Blocks.WARPED_WART_BLOCK));
+ public static final Item RED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICKS));
+ public static final Item BONE_BLOCK = register(new BlockItem(builder(), Blocks.BONE_BLOCK));
+ public static final Item STRUCTURE_VOID = register(new BlockItem(builder(), Blocks.STRUCTURE_VOID));
+ public static final Item SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.SHULKER_BOX));
+ public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.WHITE_SHULKER_BOX));
+ public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.ORANGE_SHULKER_BOX));
+ public static final Item MAGENTA_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.MAGENTA_SHULKER_BOX));
+ public static final Item LIGHT_BLUE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIGHT_BLUE_SHULKER_BOX));
+ public static final Item YELLOW_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.YELLOW_SHULKER_BOX));
+ public static final Item LIME_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIME_SHULKER_BOX));
+ public static final Item PINK_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.PINK_SHULKER_BOX));
+ public static final Item GRAY_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.GRAY_SHULKER_BOX));
+ public static final Item LIGHT_GRAY_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIGHT_GRAY_SHULKER_BOX));
+ public static final Item CYAN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.CYAN_SHULKER_BOX));
+ public static final Item PURPLE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.PURPLE_SHULKER_BOX));
+ public static final Item BLUE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BLUE_SHULKER_BOX));
+ public static final Item BROWN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BROWN_SHULKER_BOX));
+ public static final Item GREEN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.GREEN_SHULKER_BOX));
+ public static final Item RED_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.RED_SHULKER_BOX));
+ public static final Item BLACK_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BLACK_SHULKER_BOX));
+ public static final Item WHITE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.WHITE_GLAZED_TERRACOTTA));
+ public static final Item ORANGE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.ORANGE_GLAZED_TERRACOTTA));
+ public static final Item MAGENTA_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.MAGENTA_GLAZED_TERRACOTTA));
+ public static final Item LIGHT_BLUE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_GLAZED_TERRACOTTA));
+ public static final Item YELLOW_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.YELLOW_GLAZED_TERRACOTTA));
+ public static final Item LIME_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIME_GLAZED_TERRACOTTA));
+ public static final Item PINK_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.PINK_GLAZED_TERRACOTTA));
+ public static final Item GRAY_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.GRAY_GLAZED_TERRACOTTA));
+ public static final Item LIGHT_GRAY_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_GLAZED_TERRACOTTA));
+ public static final Item CYAN_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.CYAN_GLAZED_TERRACOTTA));
+ public static final Item PURPLE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.PURPLE_GLAZED_TERRACOTTA));
+ public static final Item BLUE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLUE_GLAZED_TERRACOTTA));
+ public static final Item BROWN_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.BROWN_GLAZED_TERRACOTTA));
+ public static final Item GREEN_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.GREEN_GLAZED_TERRACOTTA));
+ public static final Item RED_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.RED_GLAZED_TERRACOTTA));
+ public static final Item BLACK_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLACK_GLAZED_TERRACOTTA));
+ public static final Item WHITE_CONCRETE = register(new BlockItem(builder(), Blocks.WHITE_CONCRETE));
+ public static final Item ORANGE_CONCRETE = register(new BlockItem(builder(), Blocks.ORANGE_CONCRETE));
+ public static final Item MAGENTA_CONCRETE = register(new BlockItem(builder(), Blocks.MAGENTA_CONCRETE));
+ public static final Item LIGHT_BLUE_CONCRETE = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CONCRETE));
+ public static final Item YELLOW_CONCRETE = register(new BlockItem(builder(), Blocks.YELLOW_CONCRETE));
+ public static final Item LIME_CONCRETE = register(new BlockItem(builder(), Blocks.LIME_CONCRETE));
+ public static final Item PINK_CONCRETE = register(new BlockItem(builder(), Blocks.PINK_CONCRETE));
+ public static final Item GRAY_CONCRETE = register(new BlockItem(builder(), Blocks.GRAY_CONCRETE));
+ public static final Item LIGHT_GRAY_CONCRETE = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CONCRETE));
+ public static final Item CYAN_CONCRETE = register(new BlockItem(builder(), Blocks.CYAN_CONCRETE));
+ public static final Item PURPLE_CONCRETE = register(new BlockItem(builder(), Blocks.PURPLE_CONCRETE));
+ public static final Item BLUE_CONCRETE = register(new BlockItem(builder(), Blocks.BLUE_CONCRETE));
+ public static final Item BROWN_CONCRETE = register(new BlockItem(builder(), Blocks.BROWN_CONCRETE));
+ public static final Item GREEN_CONCRETE = register(new BlockItem(builder(), Blocks.GREEN_CONCRETE));
+ public static final Item RED_CONCRETE = register(new BlockItem(builder(), Blocks.RED_CONCRETE));
+ public static final Item BLACK_CONCRETE = register(new BlockItem(builder(), Blocks.BLACK_CONCRETE));
+ public static final Item WHITE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.WHITE_CONCRETE_POWDER));
+ public static final Item ORANGE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.ORANGE_CONCRETE_POWDER));
+ public static final Item MAGENTA_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.MAGENTA_CONCRETE_POWDER));
+ public static final Item LIGHT_BLUE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CONCRETE_POWDER));
+ public static final Item YELLOW_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.YELLOW_CONCRETE_POWDER));
+ public static final Item LIME_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.LIME_CONCRETE_POWDER));
+ public static final Item PINK_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.PINK_CONCRETE_POWDER));
+ public static final Item GRAY_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.GRAY_CONCRETE_POWDER));
+ public static final Item LIGHT_GRAY_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CONCRETE_POWDER));
+ public static final Item CYAN_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.CYAN_CONCRETE_POWDER));
+ public static final Item PURPLE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.PURPLE_CONCRETE_POWDER));
+ public static final Item BLUE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.BLUE_CONCRETE_POWDER));
+ public static final Item BROWN_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.BROWN_CONCRETE_POWDER));
+ public static final Item GREEN_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.GREEN_CONCRETE_POWDER));
+ public static final Item RED_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.RED_CONCRETE_POWDER));
+ public static final Item BLACK_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.BLACK_CONCRETE_POWDER));
+ public static final Item TURTLE_EGG = register(new BlockItem(builder(), Blocks.TURTLE_EGG));
+ public static final Item SNIFFER_EGG = register(new BlockItem(builder(), Blocks.SNIFFER_EGG));
+ public static final Item DEAD_TUBE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_TUBE_CORAL_BLOCK));
+ public static final Item DEAD_BRAIN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_BRAIN_CORAL_BLOCK));
+ public static final Item DEAD_BUBBLE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_BUBBLE_CORAL_BLOCK));
+ public static final Item DEAD_FIRE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL_BLOCK));
+ public static final Item DEAD_HORN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL_BLOCK));
+ public static final Item TUBE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.TUBE_CORAL_BLOCK));
+ public static final Item BRAIN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.BRAIN_CORAL_BLOCK));
+ public static final Item BUBBLE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.BUBBLE_CORAL_BLOCK));
+ public static final Item FIRE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.FIRE_CORAL_BLOCK));
+ public static final Item HORN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.HORN_CORAL_BLOCK));
+ public static final Item TUBE_CORAL = register(new BlockItem(builder(), Blocks.TUBE_CORAL));
+ public static final Item BRAIN_CORAL = register(new BlockItem(builder(), Blocks.BRAIN_CORAL));
+ public static final Item BUBBLE_CORAL = register(new BlockItem(builder(), Blocks.BUBBLE_CORAL));
+ public static final Item FIRE_CORAL = register(new BlockItem(builder(), Blocks.FIRE_CORAL));
+ public static final Item HORN_CORAL = register(new BlockItem(builder(), Blocks.HORN_CORAL));
+ public static final Item DEAD_BRAIN_CORAL = register(new BlockItem(builder(), Blocks.DEAD_BRAIN_CORAL));
+ public static final Item DEAD_BUBBLE_CORAL = register(new BlockItem(builder(), Blocks.DEAD_BUBBLE_CORAL));
+ public static final Item DEAD_FIRE_CORAL = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL));
+ public static final Item DEAD_HORN_CORAL = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL));
+ public static final Item DEAD_TUBE_CORAL = register(new BlockItem(builder(), Blocks.DEAD_TUBE_CORAL));
+ public static final Item TUBE_CORAL_FAN = register(new BlockItem(builder(), Blocks.TUBE_CORAL_FAN, Blocks.TUBE_CORAL_WALL_FAN));
+ public static final Item BRAIN_CORAL_FAN = register(new BlockItem(builder(), Blocks.BRAIN_CORAL_FAN, Blocks.BRAIN_CORAL_WALL_FAN));
+ public static final Item BUBBLE_CORAL_FAN = register(new BlockItem(builder(), Blocks.BUBBLE_CORAL_FAN, Blocks.BUBBLE_CORAL_WALL_FAN));
+ public static final Item FIRE_CORAL_FAN = register(new BlockItem(builder(), Blocks.FIRE_CORAL_FAN, Blocks.FIRE_CORAL_WALL_FAN));
+ public static final Item HORN_CORAL_FAN = register(new BlockItem(builder(), Blocks.HORN_CORAL_FAN, Blocks.HORN_CORAL_WALL_FAN));
+ public static final Item DEAD_TUBE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_TUBE_CORAL_FAN, Blocks.DEAD_TUBE_CORAL_WALL_FAN));
+ public static final Item DEAD_BRAIN_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_BRAIN_CORAL_FAN, Blocks.DEAD_BRAIN_CORAL_WALL_FAN));
+ public static final Item DEAD_BUBBLE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_BUBBLE_CORAL_FAN, Blocks.DEAD_BUBBLE_CORAL_WALL_FAN));
+ public static final Item DEAD_FIRE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL_FAN, Blocks.DEAD_FIRE_CORAL_WALL_FAN));
+ public static final Item DEAD_HORN_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL_FAN, Blocks.DEAD_HORN_CORAL_WALL_FAN));
+ public static final Item BLUE_ICE = register(new BlockItem(builder(), Blocks.BLUE_ICE));
+ public static final Item CONDUIT = register(new BlockItem(builder(), Blocks.CONDUIT));
+ public static final Item POLISHED_GRANITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE_STAIRS));
+ public static final Item SMOOTH_RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE_STAIRS));
+ public static final Item MOSSY_STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_STAIRS));
+ public static final Item POLISHED_DIORITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_DIORITE_STAIRS));
+ public static final Item MOSSY_COBBLESTONE_STAIRS = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_STAIRS));
+ public static final Item END_STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.END_STONE_BRICK_STAIRS));
+ public static final Item STONE_STAIRS = register(new BlockItem(builder(), Blocks.STONE_STAIRS));
+ public static final Item SMOOTH_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_SANDSTONE_STAIRS));
+ public static final Item SMOOTH_QUARTZ_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_QUARTZ_STAIRS));
+ public static final Item GRANITE_STAIRS = register(new BlockItem(builder(), Blocks.GRANITE_STAIRS));
+ public static final Item ANDESITE_STAIRS = register(new BlockItem(builder(), Blocks.ANDESITE_STAIRS));
+ public static final Item RED_NETHER_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICK_STAIRS));
+ public static final Item POLISHED_ANDESITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_ANDESITE_STAIRS));
+ public static final Item DIORITE_STAIRS = register(new BlockItem(builder(), Blocks.DIORITE_STAIRS));
+ public static final Item COBBLED_DEEPSLATE_STAIRS = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE_STAIRS));
+ public static final Item POLISHED_DEEPSLATE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE_STAIRS));
+ public static final Item DEEPSLATE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICK_STAIRS));
+ public static final Item DEEPSLATE_TILE_STAIRS = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILE_STAIRS));
+ public static final Item POLISHED_GRANITE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE_SLAB));
+ public static final Item SMOOTH_RED_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE_SLAB));
+ public static final Item MOSSY_STONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_SLAB));
+ public static final Item POLISHED_DIORITE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_DIORITE_SLAB));
+ public static final Item MOSSY_COBBLESTONE_SLAB = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_SLAB));
+ public static final Item END_STONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.END_STONE_BRICK_SLAB));
+ public static final Item SMOOTH_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_SANDSTONE_SLAB));
+ public static final Item SMOOTH_QUARTZ_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_QUARTZ_SLAB));
+ public static final Item GRANITE_SLAB = register(new BlockItem(builder(), Blocks.GRANITE_SLAB));
+ public static final Item ANDESITE_SLAB = register(new BlockItem(builder(), Blocks.ANDESITE_SLAB));
+ public static final Item RED_NETHER_BRICK_SLAB = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICK_SLAB));
+ public static final Item POLISHED_ANDESITE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_ANDESITE_SLAB));
+ public static final Item DIORITE_SLAB = register(new BlockItem(builder(), Blocks.DIORITE_SLAB));
+ public static final Item COBBLED_DEEPSLATE_SLAB = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE_SLAB));
+ public static final Item POLISHED_DEEPSLATE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE_SLAB));
+ public static final Item DEEPSLATE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICK_SLAB));
+ public static final Item DEEPSLATE_TILE_SLAB = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILE_SLAB));
+ public static final Item SCAFFOLDING = register(new BlockItem(builder(), Blocks.SCAFFOLDING));
+ public static final Item REDSTONE = register(new BlockItem("redstone", builder(), Blocks.REDSTONE_WIRE));
+ public static final Item REDSTONE_TORCH = register(new BlockItem(builder(), Blocks.REDSTONE_TORCH, Blocks.REDSTONE_WALL_TORCH));
+ public static final Item REDSTONE_BLOCK = register(new BlockItem(builder(), Blocks.REDSTONE_BLOCK));
+ public static final Item REPEATER = register(new BlockItem(builder(), Blocks.REPEATER));
+ public static final Item COMPARATOR = register(new BlockItem(builder(), Blocks.COMPARATOR));
+ public static final Item PISTON = register(new BlockItem(builder(), Blocks.PISTON));
+ public static final Item STICKY_PISTON = register(new BlockItem(builder(), Blocks.STICKY_PISTON));
+ public static final Item SLIME_BLOCK = register(new BlockItem(builder(), Blocks.SLIME_BLOCK));
+ public static final Item HONEY_BLOCK = register(new BlockItem(builder(), Blocks.HONEY_BLOCK));
+ public static final Item OBSERVER = register(new BlockItem(builder(), Blocks.OBSERVER));
+ public static final Item HOPPER = register(new BlockItem(builder(), Blocks.HOPPER));
+ public static final Item DISPENSER = register(new BlockItem(builder(), Blocks.DISPENSER));
+ public static final Item DROPPER = register(new BlockItem(builder(), Blocks.DROPPER));
+ public static final Item LECTERN = register(new BlockItem(builder(), Blocks.LECTERN));
+ public static final Item TARGET = register(new BlockItem(builder(), Blocks.TARGET));
+ public static final Item LEVER = register(new BlockItem(builder(), Blocks.LEVER));
+ public static final Item LIGHTNING_ROD = register(new BlockItem(builder(), Blocks.LIGHTNING_ROD));
+ public static final Item DAYLIGHT_DETECTOR = register(new BlockItem(builder(), Blocks.DAYLIGHT_DETECTOR));
+ public static final Item SCULK_SENSOR = register(new BlockItem(builder(), Blocks.SCULK_SENSOR));
+ public static final Item CALIBRATED_SCULK_SENSOR = register(new BlockItem(builder(), Blocks.CALIBRATED_SCULK_SENSOR));
+ public static final Item TRIPWIRE_HOOK = register(new BlockItem(builder(), Blocks.TRIPWIRE_HOOK));
+ public static final Item TRAPPED_CHEST = register(new BlockItem(builder(), Blocks.TRAPPED_CHEST));
+ public static final Item TNT = register(new BlockItem(builder(), Blocks.TNT));
+ public static final Item REDSTONE_LAMP = register(new BlockItem(builder(), Blocks.REDSTONE_LAMP));
+ public static final Item NOTE_BLOCK = register(new BlockItem(builder(), Blocks.NOTE_BLOCK));
+ public static final Item STONE_BUTTON = register(new BlockItem(builder(), Blocks.STONE_BUTTON));
+ public static final Item POLISHED_BLACKSTONE_BUTTON = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BUTTON));
+ public static final Item OAK_BUTTON = register(new BlockItem(builder(), Blocks.OAK_BUTTON));
+ public static final Item SPRUCE_BUTTON = register(new BlockItem(builder(), Blocks.SPRUCE_BUTTON));
+ public static final Item BIRCH_BUTTON = register(new BlockItem(builder(), Blocks.BIRCH_BUTTON));
+ public static final Item JUNGLE_BUTTON = register(new BlockItem(builder(), Blocks.JUNGLE_BUTTON));
+ public static final Item ACACIA_BUTTON = register(new BlockItem(builder(), Blocks.ACACIA_BUTTON));
+ public static final Item CHERRY_BUTTON = register(new BlockItem(builder(), Blocks.CHERRY_BUTTON));
+ public static final Item DARK_OAK_BUTTON = register(new BlockItem(builder(), Blocks.DARK_OAK_BUTTON));
+ public static final Item MANGROVE_BUTTON = register(new BlockItem(builder(), Blocks.MANGROVE_BUTTON));
+ public static final Item BAMBOO_BUTTON = register(new BlockItem(builder(), Blocks.BAMBOO_BUTTON));
+ public static final Item CRIMSON_BUTTON = register(new BlockItem(builder(), Blocks.CRIMSON_BUTTON));
+ public static final Item WARPED_BUTTON = register(new BlockItem(builder(), Blocks.WARPED_BUTTON));
+ public static final Item STONE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.STONE_PRESSURE_PLATE));
+ public static final Item POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_PRESSURE_PLATE));
+ public static final Item LIGHT_WEIGHTED_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.LIGHT_WEIGHTED_PRESSURE_PLATE));
+ public static final Item HEAVY_WEIGHTED_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE));
+ public static final Item OAK_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.OAK_PRESSURE_PLATE));
+ public static final Item SPRUCE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.SPRUCE_PRESSURE_PLATE));
+ public static final Item BIRCH_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.BIRCH_PRESSURE_PLATE));
+ public static final Item JUNGLE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.JUNGLE_PRESSURE_PLATE));
+ public static final Item ACACIA_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.ACACIA_PRESSURE_PLATE));
+ public static final Item CHERRY_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.CHERRY_PRESSURE_PLATE));
+ public static final Item DARK_OAK_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.DARK_OAK_PRESSURE_PLATE));
+ public static final Item MANGROVE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.MANGROVE_PRESSURE_PLATE));
+ public static final Item BAMBOO_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.BAMBOO_PRESSURE_PLATE));
+ public static final Item CRIMSON_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.CRIMSON_PRESSURE_PLATE));
+ public static final Item WARPED_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.WARPED_PRESSURE_PLATE));
+ public static final Item IRON_DOOR = register(new BlockItem(builder(), Blocks.IRON_DOOR));
+ public static final Item OAK_DOOR = register(new BlockItem(builder(), Blocks.OAK_DOOR));
+ public static final Item SPRUCE_DOOR = register(new BlockItem(builder(), Blocks.SPRUCE_DOOR));
+ public static final Item BIRCH_DOOR = register(new BlockItem(builder(), Blocks.BIRCH_DOOR));
+ public static final Item JUNGLE_DOOR = register(new BlockItem(builder(), Blocks.JUNGLE_DOOR));
+ public static final Item ACACIA_DOOR = register(new BlockItem(builder(), Blocks.ACACIA_DOOR));
+ public static final Item CHERRY_DOOR = register(new BlockItem(builder(), Blocks.CHERRY_DOOR));
+ public static final Item DARK_OAK_DOOR = register(new BlockItem(builder(), Blocks.DARK_OAK_DOOR));
+ public static final Item MANGROVE_DOOR = register(new BlockItem(builder(), Blocks.MANGROVE_DOOR));
+ public static final Item BAMBOO_DOOR = register(new BlockItem(builder(), Blocks.BAMBOO_DOOR));
+ public static final Item CRIMSON_DOOR = register(new BlockItem(builder(), Blocks.CRIMSON_DOOR));
+ public static final Item WARPED_DOOR = register(new BlockItem(builder(), Blocks.WARPED_DOOR));
+ public static final Item COPPER_DOOR = register(new BlockItem(builder(), Blocks.COPPER_DOOR));
+ public static final Item EXPOSED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_DOOR));
+ public static final Item WEATHERED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_DOOR));
+ public static final Item OXIDIZED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_DOOR));
+ public static final Item WAXED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_COPPER_DOOR));
+ public static final Item WAXED_EXPOSED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_DOOR));
+ public static final Item WAXED_WEATHERED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_DOOR));
+ public static final Item WAXED_OXIDIZED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_DOOR));
+ public static final Item IRON_TRAPDOOR = register(new BlockItem(builder(), Blocks.IRON_TRAPDOOR));
+ public static final Item OAK_TRAPDOOR = register(new BlockItem(builder(), Blocks.OAK_TRAPDOOR));
+ public static final Item SPRUCE_TRAPDOOR = register(new BlockItem(builder(), Blocks.SPRUCE_TRAPDOOR));
+ public static final Item BIRCH_TRAPDOOR = register(new BlockItem(builder(), Blocks.BIRCH_TRAPDOOR));
+ public static final Item JUNGLE_TRAPDOOR = register(new BlockItem(builder(), Blocks.JUNGLE_TRAPDOOR));
+ public static final Item ACACIA_TRAPDOOR = register(new BlockItem(builder(), Blocks.ACACIA_TRAPDOOR));
+ public static final Item CHERRY_TRAPDOOR = register(new BlockItem(builder(), Blocks.CHERRY_TRAPDOOR));
+ public static final Item DARK_OAK_TRAPDOOR = register(new BlockItem(builder(), Blocks.DARK_OAK_TRAPDOOR));
+ public static final Item MANGROVE_TRAPDOOR = register(new BlockItem(builder(), Blocks.MANGROVE_TRAPDOOR));
+ public static final Item BAMBOO_TRAPDOOR = register(new BlockItem(builder(), Blocks.BAMBOO_TRAPDOOR));
+ public static final Item CRIMSON_TRAPDOOR = register(new BlockItem(builder(), Blocks.CRIMSON_TRAPDOOR));
+ public static final Item WARPED_TRAPDOOR = register(new BlockItem(builder(), Blocks.WARPED_TRAPDOOR));
+ public static final Item COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.COPPER_TRAPDOOR));
+ public static final Item EXPOSED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_TRAPDOOR));
+ public static final Item WEATHERED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_TRAPDOOR));
+ public static final Item OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_TRAPDOOR));
+ public static final Item WAXED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_COPPER_TRAPDOOR));
+ public static final Item WAXED_EXPOSED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_TRAPDOOR));
+ public static final Item WAXED_WEATHERED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_TRAPDOOR));
+ public static final Item WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_TRAPDOOR));
+ public static final Item OAK_FENCE_GATE = register(new BlockItem(builder(), Blocks.OAK_FENCE_GATE));
+ public static final Item SPRUCE_FENCE_GATE = register(new BlockItem(builder(), Blocks.SPRUCE_FENCE_GATE));
+ public static final Item BIRCH_FENCE_GATE = register(new BlockItem(builder(), Blocks.BIRCH_FENCE_GATE));
+ public static final Item JUNGLE_FENCE_GATE = register(new BlockItem(builder(), Blocks.JUNGLE_FENCE_GATE));
+ public static final Item ACACIA_FENCE_GATE = register(new BlockItem(builder(), Blocks.ACACIA_FENCE_GATE));
+ public static final Item CHERRY_FENCE_GATE = register(new BlockItem(builder(), Blocks.CHERRY_FENCE_GATE));
+ public static final Item DARK_OAK_FENCE_GATE = register(new BlockItem(builder(), Blocks.DARK_OAK_FENCE_GATE));
+ public static final Item MANGROVE_FENCE_GATE = register(new BlockItem(builder(), Blocks.MANGROVE_FENCE_GATE));
+ public static final Item BAMBOO_FENCE_GATE = register(new BlockItem(builder(), Blocks.BAMBOO_FENCE_GATE));
+ public static final Item CRIMSON_FENCE_GATE = register(new BlockItem(builder(), Blocks.CRIMSON_FENCE_GATE));
+ public static final Item WARPED_FENCE_GATE = register(new BlockItem(builder(), Blocks.WARPED_FENCE_GATE));
+ public static final Item POWERED_RAIL = register(new BlockItem(builder(), Blocks.POWERED_RAIL));
+ public static final Item DETECTOR_RAIL = register(new BlockItem(builder(), Blocks.DETECTOR_RAIL));
+ public static final Item RAIL = register(new BlockItem(builder(), Blocks.RAIL));
+ public static final Item ACTIVATOR_RAIL = register(new BlockItem(builder(), Blocks.ACTIVATOR_RAIL));
public static final Item SADDLE = register(new Item("saddle", builder().stackSize(1)));
public static final Item MINECART = register(new Item("minecart", builder().stackSize(1)));
public static final Item CHEST_MINECART = register(new Item("chest_minecart", builder().stackSize(1)));
@@ -830,8 +829,8 @@ public final class Items {
public static final Item MANGROVE_CHEST_BOAT = register(new BoatItem("mangrove_chest_boat", builder().stackSize(1)));
public static final Item BAMBOO_RAFT = register(new BoatItem("bamboo_raft", builder().stackSize(1)));
public static final Item BAMBOO_CHEST_RAFT = register(new BoatItem("bamboo_chest_raft", builder().stackSize(1)));
- public static final Item STRUCTURE_BLOCK = register(new BlockItem("structure_block", builder()));
- public static final Item JIGSAW = register(new BlockItem("jigsaw", builder()));
+ public static final Item STRUCTURE_BLOCK = register(new BlockItem(builder(), Blocks.STRUCTURE_BLOCK));
+ public static final Item JIGSAW = register(new BlockItem(builder(), Blocks.JIGSAW));
public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", ArmorMaterial.TURTLE, builder().stackSize(1).maxDamage(275)));
public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder()));
public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder()));
@@ -888,10 +887,10 @@ public final class Items {
public static final Item STICK = register(new Item("stick", builder()));
public static final Item BOWL = register(new Item("bowl", builder()));
public static final Item MUSHROOM_STEW = register(new Item("mushroom_stew", builder().stackSize(1)));
- public static final Item STRING = register(new BlockItem("string", builder()));
+ public static final Item STRING = register(new BlockItem("string", builder(), Blocks.TRIPWIRE));
public static final Item FEATHER = register(new Item("feather", builder()));
public static final Item GUNPOWDER = register(new Item("gunpowder", builder()));
- public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder()));
+ public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder(), Blocks.WHEAT));
public static final Item WHEAT = register(new Item("wheat", builder()));
public static final Item BREAD = register(new Item("bread", builder()));
public static final Item LEATHER_HELMET = register(new DyeableArmorItem("leather_helmet", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(55)));
@@ -924,32 +923,32 @@ public final class Items {
public static final Item PAINTING = register(new Item("painting", builder()));
public static final Item GOLDEN_APPLE = register(new Item("golden_apple", builder()));
public static final Item ENCHANTED_GOLDEN_APPLE = register(new Item("enchanted_golden_apple", builder()));
- public static final Item OAK_SIGN = register(new BlockItem("oak_sign", builder().stackSize(16)));
- public static final Item SPRUCE_SIGN = register(new BlockItem("spruce_sign", builder().stackSize(16)));
- public static final Item BIRCH_SIGN = register(new BlockItem("birch_sign", builder().stackSize(16)));
- public static final Item JUNGLE_SIGN = register(new BlockItem("jungle_sign", builder().stackSize(16)));
- public static final Item ACACIA_SIGN = register(new BlockItem("acacia_sign", builder().stackSize(16)));
- public static final Item CHERRY_SIGN = register(new BlockItem("cherry_sign", builder().stackSize(16)));
- public static final Item DARK_OAK_SIGN = register(new BlockItem("dark_oak_sign", builder().stackSize(16)));
- public static final Item MANGROVE_SIGN = register(new BlockItem("mangrove_sign", builder().stackSize(16)));
- public static final Item BAMBOO_SIGN = register(new BlockItem("bamboo_sign", builder().stackSize(16)));
- public static final Item CRIMSON_SIGN = register(new BlockItem("crimson_sign", builder().stackSize(16)));
- public static final Item WARPED_SIGN = register(new BlockItem("warped_sign", builder().stackSize(16)));
- public static final Item OAK_HANGING_SIGN = register(new BlockItem("oak_hanging_sign", builder().stackSize(16)));
- public static final Item SPRUCE_HANGING_SIGN = register(new BlockItem("spruce_hanging_sign", builder().stackSize(16)));
- public static final Item BIRCH_HANGING_SIGN = register(new BlockItem("birch_hanging_sign", builder().stackSize(16)));
- public static final Item JUNGLE_HANGING_SIGN = register(new BlockItem("jungle_hanging_sign", builder().stackSize(16)));
- public static final Item ACACIA_HANGING_SIGN = register(new BlockItem("acacia_hanging_sign", builder().stackSize(16)));
- public static final Item CHERRY_HANGING_SIGN = register(new BlockItem("cherry_hanging_sign", builder().stackSize(16)));
- public static final Item DARK_OAK_HANGING_SIGN = register(new BlockItem("dark_oak_hanging_sign", builder().stackSize(16)));
- public static final Item MANGROVE_HANGING_SIGN = register(new BlockItem("mangrove_hanging_sign", builder().stackSize(16)));
- public static final Item BAMBOO_HANGING_SIGN = register(new BlockItem("bamboo_hanging_sign", builder().stackSize(16)));
- public static final Item CRIMSON_HANGING_SIGN = register(new BlockItem("crimson_hanging_sign", builder().stackSize(16)));
- public static final Item WARPED_HANGING_SIGN = register(new BlockItem("warped_hanging_sign", builder().stackSize(16)));
+ public static final Item OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_SIGN, Blocks.OAK_WALL_SIGN));
+ public static final Item SPRUCE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_SIGN, Blocks.SPRUCE_WALL_SIGN));
+ public static final Item BIRCH_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_SIGN, Blocks.BIRCH_WALL_SIGN));
+ public static final Item JUNGLE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.JUNGLE_SIGN, Blocks.JUNGLE_WALL_SIGN));
+ public static final Item ACACIA_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_SIGN, Blocks.ACACIA_WALL_SIGN));
+ public static final Item CHERRY_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_SIGN, Blocks.CHERRY_WALL_SIGN));
+ public static final Item DARK_OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_SIGN, Blocks.DARK_OAK_WALL_SIGN));
+ public static final Item MANGROVE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_SIGN, Blocks.MANGROVE_WALL_SIGN));
+ public static final Item BAMBOO_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_SIGN, Blocks.BAMBOO_WALL_SIGN));
+ public static final Item CRIMSON_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_SIGN, Blocks.CRIMSON_WALL_SIGN));
+ public static final Item WARPED_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.WARPED_SIGN, Blocks.WARPED_WALL_SIGN));
+ public static final Item OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_HANGING_SIGN, Blocks.OAK_WALL_HANGING_SIGN));
+ public static final Item SPRUCE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_HANGING_SIGN, Blocks.SPRUCE_WALL_HANGING_SIGN));
+ public static final Item BIRCH_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_HANGING_SIGN, Blocks.BIRCH_WALL_HANGING_SIGN));
+ public static final Item JUNGLE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.JUNGLE_HANGING_SIGN, Blocks.JUNGLE_WALL_HANGING_SIGN));
+ public static final Item ACACIA_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_HANGING_SIGN, Blocks.ACACIA_WALL_HANGING_SIGN));
+ public static final Item CHERRY_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_HANGING_SIGN, Blocks.CHERRY_WALL_HANGING_SIGN));
+ public static final Item DARK_OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_HANGING_SIGN, Blocks.DARK_OAK_WALL_HANGING_SIGN));
+ public static final Item MANGROVE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_HANGING_SIGN, Blocks.MANGROVE_WALL_HANGING_SIGN));
+ public static final Item BAMBOO_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_HANGING_SIGN, Blocks.BAMBOO_WALL_HANGING_SIGN));
+ public static final Item CRIMSON_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_HANGING_SIGN, Blocks.CRIMSON_WALL_HANGING_SIGN));
+ public static final Item WARPED_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.WARPED_HANGING_SIGN, Blocks.WARPED_WALL_HANGING_SIGN));
public static final Item BUCKET = register(new Item("bucket", builder().stackSize(16)));
public static final Item WATER_BUCKET = register(new Item("water_bucket", builder().stackSize(1)));
public static final Item LAVA_BUCKET = register(new Item("lava_bucket", builder().stackSize(1)));
- public static final Item POWDER_SNOW_BUCKET = register(new BlockItem("powder_snow_bucket", builder().stackSize(1)));
+ public static final Item POWDER_SNOW_BUCKET = register(new BlockItem("powder_snow_bucket", builder().stackSize(1), Blocks.POWDER_SNOW));
public static final Item SNOWBALL = register(new Item("snowball", builder().stackSize(16)));
public static final Item LEATHER = register(new Item("leather", builder()));
public static final Item MILK_BUCKET = register(new Item("milk_bucket", builder().stackSize(1)));
@@ -961,7 +960,7 @@ public final class Items {
public static final Item TADPOLE_BUCKET = register(new Item("tadpole_bucket", builder().stackSize(1)));
public static final Item BRICK = register(new Item("brick", builder()));
public static final Item CLAY_BALL = register(new Item("clay_ball", builder()));
- public static final Item DRIED_KELP_BLOCK = register(new BlockItem("dried_kelp_block", builder()));
+ public static final Item DRIED_KELP_BLOCK = register(new BlockItem(builder(), Blocks.DRIED_KELP_BLOCK));
public static final Item PAPER = register(new Item("paper", builder()));
public static final Item BOOK = register(new Item("book", builder()));
public static final Item SLIME_BALL = register(new Item("slime_ball", builder()));
@@ -981,7 +980,7 @@ public final class Items {
public static final Item COOKED_SALMON = register(new Item("cooked_salmon", builder()));
public static final Item INK_SAC = register(new Item("ink_sac", builder()));
public static final Item GLOW_INK_SAC = register(new Item("glow_ink_sac", builder()));
- public static final Item COCOA_BEANS = register(new BlockItem("cocoa_beans", builder()));
+ public static final Item COCOA_BEANS = register(new BlockItem("cocoa_beans", builder(), Blocks.COCOA));
public static final Item WHITE_DYE = register(new DyeItem("white_dye", 0, builder()));
public static final Item ORANGE_DYE = register(new DyeItem("orange_dye", 1, builder()));
public static final Item MAGENTA_DYE = register(new DyeItem("magenta_dye", 2, builder()));
@@ -1001,31 +1000,31 @@ public final class Items {
public static final Item BONE_MEAL = register(new Item("bone_meal", builder()));
public static final Item BONE = register(new Item("bone", builder()));
public static final Item SUGAR = register(new Item("sugar", builder()));
- public static final Item CAKE = register(new BlockItem("cake", builder().stackSize(1)));
- public static final Item WHITE_BED = register(new BlockItem("white_bed", builder().stackSize(1)));
- public static final Item ORANGE_BED = register(new BlockItem("orange_bed", builder().stackSize(1)));
- public static final Item MAGENTA_BED = register(new BlockItem("magenta_bed", builder().stackSize(1)));
- public static final Item LIGHT_BLUE_BED = register(new BlockItem("light_blue_bed", builder().stackSize(1)));
- public static final Item YELLOW_BED = register(new BlockItem("yellow_bed", builder().stackSize(1)));
- public static final Item LIME_BED = register(new BlockItem("lime_bed", builder().stackSize(1)));
- public static final Item PINK_BED = register(new BlockItem("pink_bed", builder().stackSize(1)));
- public static final Item GRAY_BED = register(new BlockItem("gray_bed", builder().stackSize(1)));
- public static final Item LIGHT_GRAY_BED = register(new BlockItem("light_gray_bed", builder().stackSize(1)));
- public static final Item CYAN_BED = register(new BlockItem("cyan_bed", builder().stackSize(1)));
- public static final Item PURPLE_BED = register(new BlockItem("purple_bed", builder().stackSize(1)));
- public static final Item BLUE_BED = register(new BlockItem("blue_bed", builder().stackSize(1)));
- public static final Item BROWN_BED = register(new BlockItem("brown_bed", builder().stackSize(1)));
- public static final Item GREEN_BED = register(new BlockItem("green_bed", builder().stackSize(1)));
- public static final Item RED_BED = register(new BlockItem("red_bed", builder().stackSize(1)));
- public static final Item BLACK_BED = register(new BlockItem("black_bed", builder().stackSize(1)));
+ public static final Item CAKE = register(new BlockItem(builder().stackSize(1), Blocks.CAKE));
+ public static final Item WHITE_BED = register(new BlockItem(builder().stackSize(1), Blocks.WHITE_BED));
+ public static final Item ORANGE_BED = register(new BlockItem(builder().stackSize(1), Blocks.ORANGE_BED));
+ public static final Item MAGENTA_BED = register(new BlockItem(builder().stackSize(1), Blocks.MAGENTA_BED));
+ public static final Item LIGHT_BLUE_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIGHT_BLUE_BED));
+ public static final Item YELLOW_BED = register(new BlockItem(builder().stackSize(1), Blocks.YELLOW_BED));
+ public static final Item LIME_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIME_BED));
+ public static final Item PINK_BED = register(new BlockItem(builder().stackSize(1), Blocks.PINK_BED));
+ public static final Item GRAY_BED = register(new BlockItem(builder().stackSize(1), Blocks.GRAY_BED));
+ public static final Item LIGHT_GRAY_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIGHT_GRAY_BED));
+ public static final Item CYAN_BED = register(new BlockItem(builder().stackSize(1), Blocks.CYAN_BED));
+ public static final Item PURPLE_BED = register(new BlockItem(builder().stackSize(1), Blocks.PURPLE_BED));
+ public static final Item BLUE_BED = register(new BlockItem(builder().stackSize(1), Blocks.BLUE_BED));
+ public static final Item BROWN_BED = register(new BlockItem(builder().stackSize(1), Blocks.BROWN_BED));
+ public static final Item GREEN_BED = register(new BlockItem(builder().stackSize(1), Blocks.GREEN_BED));
+ public static final Item RED_BED = register(new BlockItem(builder().stackSize(1), Blocks.RED_BED));
+ public static final Item BLACK_BED = register(new BlockItem(builder().stackSize(1), Blocks.BLACK_BED));
public static final Item COOKIE = register(new Item("cookie", builder()));
- public static final Item CRAFTER = register(new BlockItem("crafter", builder()));
+ public static final Item CRAFTER = register(new BlockItem(builder(), Blocks.CRAFTER));
public static final Item FILLED_MAP = register(new FilledMapItem("filled_map", builder()));
public static final Item SHEARS = register(new Item("shears", builder().stackSize(1).maxDamage(238)));
public static final Item MELON_SLICE = register(new Item("melon_slice", builder()));
public static final Item DRIED_KELP = register(new Item("dried_kelp", builder()));
- public static final Item PUMPKIN_SEEDS = register(new BlockItem("pumpkin_seeds", builder()));
- public static final Item MELON_SEEDS = register(new BlockItem("melon_seeds", builder()));
+ public static final Item PUMPKIN_SEEDS = register(new BlockItem("pumpkin_seeds", builder(), Blocks.PUMPKIN_STEM));
+ public static final Item MELON_SEEDS = register(new BlockItem("melon_seeds", builder(), Blocks.MELON_STEM));
public static final Item BEEF = register(new Item("beef", builder()));
public static final Item COOKED_BEEF = register(new Item("cooked_beef", builder()));
public static final Item CHICKEN = register(new Item("chicken", builder()));
@@ -1035,15 +1034,15 @@ public final class Items {
public static final Item BLAZE_ROD = register(new Item("blaze_rod", builder()));
public static final Item GHAST_TEAR = register(new Item("ghast_tear", builder()));
public static final Item GOLD_NUGGET = register(new Item("gold_nugget", builder()));
- public static final Item NETHER_WART = register(new BlockItem("nether_wart", builder()));
+ public static final Item NETHER_WART = register(new BlockItem(builder(), Blocks.NETHER_WART));
public static final Item POTION = register(new PotionItem("potion", builder().stackSize(1)));
public static final Item GLASS_BOTTLE = register(new Item("glass_bottle", builder()));
public static final Item SPIDER_EYE = register(new Item("spider_eye", builder()));
public static final Item FERMENTED_SPIDER_EYE = register(new Item("fermented_spider_eye", builder()));
public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder()));
public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder()));
- public static final Item BREWING_STAND = register(new BlockItem("brewing_stand", builder()));
- public static final Item CAULDRON = register(new BlockItem("cauldron", builder()));
+ public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND));
+ public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.LAVA_CAULDRON, Blocks.POWDER_SNOW_CAULDRON, Blocks.WATER_CAULDRON));
public static final Item ENDER_EYE = register(new Item("ender_eye", builder()));
public static final Item GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", builder()));
public static final Item ARMADILLO_SPAWN_EGG = register(new SpawnEggItem("armadillo_spawn_egg", builder()));
@@ -1134,20 +1133,20 @@ public final class Items {
public static final Item MACE = register(new MaceItem("mace", builder().stackSize(1).maxDamage(250)));
public static final Item ITEM_FRAME = register(new Item("item_frame", builder()));
public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder()));
- public static final Item FLOWER_POT = register(new BlockItem("flower_pot", builder()));
- public static final Item CARROT = register(new BlockItem("carrot", builder()));
- public static final Item POTATO = register(new BlockItem("potato", builder()));
+ public static final Item FLOWER_POT = register(new BlockItem(builder(), Blocks.FLOWER_POT));
+ public static final Item CARROT = register(new BlockItem("carrot", builder(), Blocks.CARROTS));
+ public static final Item POTATO = register(new BlockItem("potato", builder(), Blocks.POTATOES));
public static final Item BAKED_POTATO = register(new Item("baked_potato", builder()));
public static final Item POISONOUS_POTATO = register(new Item("poisonous_potato", builder()));
public static final Item MAP = register(new MapItem("map", builder()));
public static final Item GOLDEN_CARROT = register(new Item("golden_carrot", builder()));
- public static final Item SKELETON_SKULL = register(new BlockItem("skeleton_skull", builder()));
- public static final Item WITHER_SKELETON_SKULL = register(new BlockItem("wither_skeleton_skull", builder()));
- public static final Item PLAYER_HEAD = register(new PlayerHeadItem("player_head", builder()));
- public static final Item ZOMBIE_HEAD = register(new BlockItem("zombie_head", builder()));
- public static final Item CREEPER_HEAD = register(new BlockItem("creeper_head", builder()));
- public static final Item DRAGON_HEAD = register(new BlockItem("dragon_head", builder()));
- public static final Item PIGLIN_HEAD = register(new BlockItem("piglin_head", builder()));
+ public static final Item SKELETON_SKULL = register(new BlockItem(builder(), Blocks.SKELETON_SKULL, Blocks.SKELETON_WALL_SKULL));
+ public static final Item WITHER_SKELETON_SKULL = register(new BlockItem(builder(), Blocks.WITHER_SKELETON_SKULL, Blocks.WITHER_SKELETON_WALL_SKULL));
+ public static final Item PLAYER_HEAD = register(new PlayerHeadItem(builder(), Blocks.PLAYER_HEAD, Blocks.PLAYER_WALL_HEAD));
+ public static final Item ZOMBIE_HEAD = register(new BlockItem(builder(), Blocks.ZOMBIE_HEAD, Blocks.ZOMBIE_WALL_HEAD));
+ public static final Item CREEPER_HEAD = register(new BlockItem(builder(), Blocks.CREEPER_HEAD, Blocks.CREEPER_WALL_HEAD));
+ public static final Item DRAGON_HEAD = register(new BlockItem(builder(), Blocks.DRAGON_HEAD, Blocks.DRAGON_WALL_HEAD));
+ public static final Item PIGLIN_HEAD = register(new BlockItem(builder(), Blocks.PIGLIN_HEAD, Blocks.PIGLIN_WALL_HEAD));
public static final Item NETHER_STAR = register(new Item("nether_star", builder()));
public static final Item PUMPKIN_PIE = register(new Item("pumpkin_pie", builder()));
public static final Item FIREWORK_ROCKET = register(new FireworkRocketItem("firework_rocket", builder()));
@@ -1171,29 +1170,29 @@ public final class Items {
public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1)));
public static final Item MUTTON = register(new Item("mutton", builder()));
public static final Item COOKED_MUTTON = register(new Item("cooked_mutton", builder()));
- public static final Item WHITE_BANNER = register(new BannerItem("white_banner", builder().stackSize(16)));
- public static final Item ORANGE_BANNER = register(new BannerItem("orange_banner", builder().stackSize(16)));
- public static final Item MAGENTA_BANNER = register(new BannerItem("magenta_banner", builder().stackSize(16)));
- public static final Item LIGHT_BLUE_BANNER = register(new BannerItem("light_blue_banner", builder().stackSize(16)));
- public static final Item YELLOW_BANNER = register(new BannerItem("yellow_banner", builder().stackSize(16)));
- public static final Item LIME_BANNER = register(new BannerItem("lime_banner", builder().stackSize(16)));
- public static final Item PINK_BANNER = register(new BannerItem("pink_banner", builder().stackSize(16)));
- public static final Item GRAY_BANNER = register(new BannerItem("gray_banner", builder().stackSize(16)));
- public static final Item LIGHT_GRAY_BANNER = register(new BannerItem("light_gray_banner", builder().stackSize(16)));
- public static final Item CYAN_BANNER = register(new BannerItem("cyan_banner", builder().stackSize(16)));
- public static final Item PURPLE_BANNER = register(new BannerItem("purple_banner", builder().stackSize(16)));
- public static final Item BLUE_BANNER = register(new BannerItem("blue_banner", builder().stackSize(16)));
- public static final Item BROWN_BANNER = register(new BannerItem("brown_banner", builder().stackSize(16)));
- public static final Item GREEN_BANNER = register(new BannerItem("green_banner", builder().stackSize(16)));
- public static final Item RED_BANNER = register(new BannerItem("red_banner", builder().stackSize(16)));
- public static final Item BLACK_BANNER = register(new BannerItem("black_banner", builder().stackSize(16)));
+ public static final Item WHITE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.WHITE_BANNER, Blocks.WHITE_WALL_BANNER));
+ public static final Item ORANGE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.ORANGE_BANNER, Blocks.ORANGE_WALL_BANNER));
+ public static final Item MAGENTA_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.MAGENTA_BANNER, Blocks.MAGENTA_WALL_BANNER));
+ public static final Item LIGHT_BLUE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIGHT_BLUE_BANNER, Blocks.LIGHT_BLUE_WALL_BANNER));
+ public static final Item YELLOW_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.YELLOW_BANNER, Blocks.YELLOW_WALL_BANNER));
+ public static final Item LIME_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIME_BANNER, Blocks.LIME_WALL_BANNER));
+ public static final Item PINK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.PINK_BANNER, Blocks.PINK_WALL_BANNER));
+ public static final Item GRAY_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GRAY_BANNER, Blocks.GRAY_WALL_BANNER));
+ public static final Item LIGHT_GRAY_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIGHT_GRAY_BANNER, Blocks.LIGHT_GRAY_WALL_BANNER));
+ public static final Item CYAN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.CYAN_BANNER, Blocks.CYAN_WALL_BANNER));
+ public static final Item PURPLE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.PURPLE_BANNER, Blocks.PURPLE_WALL_BANNER));
+ public static final Item BLUE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLUE_BANNER, Blocks.BLUE_WALL_BANNER));
+ public static final Item BROWN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BROWN_BANNER, Blocks.BROWN_WALL_BANNER));
+ public static final Item GREEN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GREEN_BANNER, Blocks.GREEN_WALL_BANNER));
+ public static final Item RED_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.RED_BANNER, Blocks.RED_WALL_BANNER));
+ public static final Item BLACK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLACK_BANNER, Blocks.BLACK_WALL_BANNER));
public static final Item END_CRYSTAL = register(new Item("end_crystal", builder()));
public static final Item CHORUS_FRUIT = register(new Item("chorus_fruit", builder()));
public static final Item POPPED_CHORUS_FRUIT = register(new Item("popped_chorus_fruit", builder()));
- public static final Item TORCHFLOWER_SEEDS = register(new BlockItem("torchflower_seeds", builder()));
- public static final Item PITCHER_POD = register(new BlockItem("pitcher_pod", builder()));
+ public static final Item TORCHFLOWER_SEEDS = register(new BlockItem("torchflower_seeds", builder(), Blocks.TORCHFLOWER_CROP));
+ public static final Item PITCHER_POD = register(new BlockItem("pitcher_pod", builder(), Blocks.PITCHER_CROP));
public static final Item BEETROOT = register(new Item("beetroot", builder()));
- public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder()));
+ public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder(), Blocks.BEETROOTS));
public static final Item BEETROOT_SOUP = register(new Item("beetroot_soup", builder().stackSize(1)));
public static final Item DRAGON_BREATH = register(new Item("dragon_breath", builder()));
public static final Item SPLASH_POTION = register(new PotionItem("splash_potion", builder().stackSize(1)));
@@ -1229,7 +1228,7 @@ public final class Items {
public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder()));
public static final Item CROSSBOW = register(new CrossbowItem("crossbow", builder().stackSize(1).maxDamage(465)));
public static final Item SUSPICIOUS_STEW = register(new Item("suspicious_stew", builder().stackSize(1)));
- public static final Item LOOM = register(new BlockItem("loom", builder()));
+ public static final Item LOOM = register(new BlockItem(builder(), Blocks.LOOM));
public static final Item FLOWER_BANNER_PATTERN = register(new Item("flower_banner_pattern", builder().stackSize(1)));
public static final Item CREEPER_BANNER_PATTERN = register(new Item("creeper_banner_pattern", builder().stackSize(1)));
public static final Item SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder().stackSize(1)));
@@ -1239,69 +1238,69 @@ public final class Items {
public static final Item FLOW_BANNER_PATTERN = register(new Item("flow_banner_pattern", builder().stackSize(1)));
public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder().stackSize(1)));
public static final Item GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1)));
- public static final Item COMPOSTER = register(new BlockItem("composter", builder()));
- public static final Item BARREL = register(new BlockItem("barrel", builder()));
- public static final Item SMOKER = register(new BlockItem("smoker", builder()));
- public static final Item BLAST_FURNACE = register(new BlockItem("blast_furnace", builder()));
- public static final Item CARTOGRAPHY_TABLE = register(new BlockItem("cartography_table", builder()));
- public static final Item FLETCHING_TABLE = register(new BlockItem("fletching_table", builder()));
- public static final Item GRINDSTONE = register(new BlockItem("grindstone", builder()));
- public static final Item SMITHING_TABLE = register(new BlockItem("smithing_table", builder()));
- public static final Item STONECUTTER = register(new BlockItem("stonecutter", builder()));
- public static final Item BELL = register(new BlockItem("bell", builder()));
- public static final Item LANTERN = register(new BlockItem("lantern", builder()));
- public static final Item SOUL_LANTERN = register(new BlockItem("soul_lantern", builder()));
- public static final Item SWEET_BERRIES = register(new BlockItem("sweet_berries", builder()));
- public static final Item GLOW_BERRIES = register(new BlockItem("glow_berries", builder()));
- public static final Item CAMPFIRE = register(new BlockItem("campfire", builder()));
- public static final Item SOUL_CAMPFIRE = register(new BlockItem("soul_campfire", builder()));
- public static final Item SHROOMLIGHT = register(new BlockItem("shroomlight", builder()));
+ public static final Item COMPOSTER = register(new BlockItem(builder(), Blocks.COMPOSTER));
+ public static final Item BARREL = register(new BlockItem(builder(), Blocks.BARREL));
+ public static final Item SMOKER = register(new BlockItem(builder(), Blocks.SMOKER));
+ public static final Item BLAST_FURNACE = register(new BlockItem(builder(), Blocks.BLAST_FURNACE));
+ public static final Item CARTOGRAPHY_TABLE = register(new BlockItem(builder(), Blocks.CARTOGRAPHY_TABLE));
+ public static final Item FLETCHING_TABLE = register(new BlockItem(builder(), Blocks.FLETCHING_TABLE));
+ public static final Item GRINDSTONE = register(new BlockItem(builder(), Blocks.GRINDSTONE));
+ public static final Item SMITHING_TABLE = register(new BlockItem(builder(), Blocks.SMITHING_TABLE));
+ public static final Item STONECUTTER = register(new BlockItem(builder(), Blocks.STONECUTTER));
+ public static final Item BELL = register(new BlockItem(builder(), Blocks.BELL));
+ public static final Item LANTERN = register(new BlockItem(builder(), Blocks.LANTERN));
+ public static final Item SOUL_LANTERN = register(new BlockItem(builder(), Blocks.SOUL_LANTERN));
+ public static final Item SWEET_BERRIES = register(new BlockItem("sweet_berries", builder(), Blocks.SWEET_BERRY_BUSH));
+ public static final Item GLOW_BERRIES = register(new BlockItem("glow_berries", builder(), Blocks.CAVE_VINES));
+ public static final Item CAMPFIRE = register(new BlockItem(builder(), Blocks.CAMPFIRE));
+ public static final Item SOUL_CAMPFIRE = register(new BlockItem(builder(), Blocks.SOUL_CAMPFIRE));
+ public static final Item SHROOMLIGHT = register(new BlockItem(builder(), Blocks.SHROOMLIGHT));
public static final Item HONEYCOMB = register(new Item("honeycomb", builder()));
- public static final Item BEE_NEST = register(new BlockItem("bee_nest", builder()));
- public static final Item BEEHIVE = register(new BlockItem("beehive", builder()));
+ public static final Item BEE_NEST = register(new BlockItem(builder(), Blocks.BEE_NEST));
+ public static final Item BEEHIVE = register(new BlockItem(builder(), Blocks.BEEHIVE));
public static final Item HONEY_BOTTLE = register(new Item("honey_bottle", builder().stackSize(16)));
- public static final Item HONEYCOMB_BLOCK = register(new BlockItem("honeycomb_block", builder()));
- public static final Item LODESTONE = register(new BlockItem("lodestone", builder()));
- public static final Item CRYING_OBSIDIAN = register(new BlockItem("crying_obsidian", builder()));
- public static final Item BLACKSTONE = register(new BlockItem("blackstone", builder()));
- public static final Item BLACKSTONE_SLAB = register(new BlockItem("blackstone_slab", builder()));
- public static final Item BLACKSTONE_STAIRS = register(new BlockItem("blackstone_stairs", builder()));
- public static final Item GILDED_BLACKSTONE = register(new BlockItem("gilded_blackstone", builder()));
- public static final Item POLISHED_BLACKSTONE = register(new BlockItem("polished_blackstone", builder()));
- public static final Item POLISHED_BLACKSTONE_SLAB = register(new BlockItem("polished_blackstone_slab", builder()));
- public static final Item POLISHED_BLACKSTONE_STAIRS = register(new BlockItem("polished_blackstone_stairs", builder()));
- public static final Item CHISELED_POLISHED_BLACKSTONE = register(new BlockItem("chiseled_polished_blackstone", builder()));
- public static final Item POLISHED_BLACKSTONE_BRICKS = register(new BlockItem("polished_blackstone_bricks", builder()));
- public static final Item POLISHED_BLACKSTONE_BRICK_SLAB = register(new BlockItem("polished_blackstone_brick_slab", builder()));
- public static final Item POLISHED_BLACKSTONE_BRICK_STAIRS = register(new BlockItem("polished_blackstone_brick_stairs", builder()));
- public static final Item CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new BlockItem("cracked_polished_blackstone_bricks", builder()));
- public static final Item RESPAWN_ANCHOR = register(new BlockItem("respawn_anchor", builder()));
- public static final Item CANDLE = register(new BlockItem("candle", builder()));
- public static final Item WHITE_CANDLE = register(new BlockItem("white_candle", builder()));
- public static final Item ORANGE_CANDLE = register(new BlockItem("orange_candle", builder()));
- public static final Item MAGENTA_CANDLE = register(new BlockItem("magenta_candle", builder()));
- public static final Item LIGHT_BLUE_CANDLE = register(new BlockItem("light_blue_candle", builder()));
- public static final Item YELLOW_CANDLE = register(new BlockItem("yellow_candle", builder()));
- public static final Item LIME_CANDLE = register(new BlockItem("lime_candle", builder()));
- public static final Item PINK_CANDLE = register(new BlockItem("pink_candle", builder()));
- public static final Item GRAY_CANDLE = register(new BlockItem("gray_candle", builder()));
- public static final Item LIGHT_GRAY_CANDLE = register(new BlockItem("light_gray_candle", builder()));
- public static final Item CYAN_CANDLE = register(new BlockItem("cyan_candle", builder()));
- public static final Item PURPLE_CANDLE = register(new BlockItem("purple_candle", builder()));
- public static final Item BLUE_CANDLE = register(new BlockItem("blue_candle", builder()));
- public static final Item BROWN_CANDLE = register(new BlockItem("brown_candle", builder()));
- public static final Item GREEN_CANDLE = register(new BlockItem("green_candle", builder()));
- public static final Item RED_CANDLE = register(new BlockItem("red_candle", builder()));
- public static final Item BLACK_CANDLE = register(new BlockItem("black_candle", builder()));
- public static final Item SMALL_AMETHYST_BUD = register(new BlockItem("small_amethyst_bud", builder()));
- public static final Item MEDIUM_AMETHYST_BUD = register(new BlockItem("medium_amethyst_bud", builder()));
- public static final Item LARGE_AMETHYST_BUD = register(new BlockItem("large_amethyst_bud", builder()));
- public static final Item AMETHYST_CLUSTER = register(new BlockItem("amethyst_cluster", builder()));
- public static final Item POINTED_DRIPSTONE = register(new BlockItem("pointed_dripstone", builder()));
- public static final Item OCHRE_FROGLIGHT = register(new BlockItem("ochre_froglight", builder()));
- public static final Item VERDANT_FROGLIGHT = register(new BlockItem("verdant_froglight", builder()));
- public static final Item PEARLESCENT_FROGLIGHT = register(new BlockItem("pearlescent_froglight", builder()));
- public static final Item FROGSPAWN = register(new BlockItem("frogspawn", builder()));
+ public static final Item HONEYCOMB_BLOCK = register(new BlockItem(builder(), Blocks.HONEYCOMB_BLOCK));
+ public static final Item LODESTONE = register(new BlockItem(builder(), Blocks.LODESTONE));
+ public static final Item CRYING_OBSIDIAN = register(new BlockItem(builder(), Blocks.CRYING_OBSIDIAN));
+ public static final Item BLACKSTONE = register(new BlockItem(builder(), Blocks.BLACKSTONE));
+ public static final Item BLACKSTONE_SLAB = register(new BlockItem(builder(), Blocks.BLACKSTONE_SLAB));
+ public static final Item BLACKSTONE_STAIRS = register(new BlockItem(builder(), Blocks.BLACKSTONE_STAIRS));
+ public static final Item GILDED_BLACKSTONE = register(new BlockItem(builder(), Blocks.GILDED_BLACKSTONE));
+ public static final Item POLISHED_BLACKSTONE = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE));
+ public static final Item POLISHED_BLACKSTONE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_SLAB));
+ public static final Item POLISHED_BLACKSTONE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_STAIRS));
+ public static final Item CHISELED_POLISHED_BLACKSTONE = register(new BlockItem(builder(), Blocks.CHISELED_POLISHED_BLACKSTONE));
+ public static final Item POLISHED_BLACKSTONE_BRICKS = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICKS));
+ public static final Item POLISHED_BLACKSTONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICK_SLAB));
+ public static final Item POLISHED_BLACKSTONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICK_STAIRS));
+ public static final Item CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_POLISHED_BLACKSTONE_BRICKS));
+ public static final Item RESPAWN_ANCHOR = register(new BlockItem(builder(), Blocks.RESPAWN_ANCHOR));
+ public static final Item CANDLE = register(new BlockItem(builder(), Blocks.CANDLE));
+ public static final Item WHITE_CANDLE = register(new BlockItem(builder(), Blocks.WHITE_CANDLE));
+ public static final Item ORANGE_CANDLE = register(new BlockItem(builder(), Blocks.ORANGE_CANDLE));
+ public static final Item MAGENTA_CANDLE = register(new BlockItem(builder(), Blocks.MAGENTA_CANDLE));
+ public static final Item LIGHT_BLUE_CANDLE = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CANDLE));
+ public static final Item YELLOW_CANDLE = register(new BlockItem(builder(), Blocks.YELLOW_CANDLE));
+ public static final Item LIME_CANDLE = register(new BlockItem(builder(), Blocks.LIME_CANDLE));
+ public static final Item PINK_CANDLE = register(new BlockItem(builder(), Blocks.PINK_CANDLE));
+ public static final Item GRAY_CANDLE = register(new BlockItem(builder(), Blocks.GRAY_CANDLE));
+ public static final Item LIGHT_GRAY_CANDLE = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CANDLE));
+ public static final Item CYAN_CANDLE = register(new BlockItem(builder(), Blocks.CYAN_CANDLE));
+ public static final Item PURPLE_CANDLE = register(new BlockItem(builder(), Blocks.PURPLE_CANDLE));
+ public static final Item BLUE_CANDLE = register(new BlockItem(builder(), Blocks.BLUE_CANDLE));
+ public static final Item BROWN_CANDLE = register(new BlockItem(builder(), Blocks.BROWN_CANDLE));
+ public static final Item GREEN_CANDLE = register(new BlockItem(builder(), Blocks.GREEN_CANDLE));
+ public static final Item RED_CANDLE = register(new BlockItem(builder(), Blocks.RED_CANDLE));
+ public static final Item BLACK_CANDLE = register(new BlockItem(builder(), Blocks.BLACK_CANDLE));
+ public static final Item SMALL_AMETHYST_BUD = register(new BlockItem(builder(), Blocks.SMALL_AMETHYST_BUD));
+ public static final Item MEDIUM_AMETHYST_BUD = register(new BlockItem(builder(), Blocks.MEDIUM_AMETHYST_BUD));
+ public static final Item LARGE_AMETHYST_BUD = register(new BlockItem(builder(), Blocks.LARGE_AMETHYST_BUD));
+ public static final Item AMETHYST_CLUSTER = register(new BlockItem(builder(), Blocks.AMETHYST_CLUSTER));
+ public static final Item POINTED_DRIPSTONE = register(new BlockItem(builder(), Blocks.POINTED_DRIPSTONE));
+ public static final Item OCHRE_FROGLIGHT = register(new BlockItem(builder(), Blocks.OCHRE_FROGLIGHT));
+ public static final Item VERDANT_FROGLIGHT = register(new BlockItem(builder(), Blocks.VERDANT_FROGLIGHT));
+ public static final Item PEARLESCENT_FROGLIGHT = register(new BlockItem(builder(), Blocks.PEARLESCENT_FROGLIGHT));
+ public static final Item FROGSPAWN = register(new BlockItem(builder(), Blocks.FROGSPAWN));
public static final Item ECHO_SHARD = register(new Item("echo_shard", builder()));
public static final Item BRUSH = register(new Item("brush", builder().stackSize(1).maxDamage(64)));
public static final Item NETHERITE_UPGRADE_SMITHING_TEMPLATE = register(new Item("netherite_upgrade_smithing_template", builder()));
@@ -1346,26 +1345,26 @@ public final class Items {
public static final Item SHELTER_POTTERY_SHERD = register(new Item("shelter_pottery_sherd", builder()));
public static final Item SKULL_POTTERY_SHERD = register(new Item("skull_pottery_sherd", builder()));
public static final Item SNORT_POTTERY_SHERD = register(new Item("snort_pottery_sherd", builder()));
- public static final Item COPPER_GRATE = register(new BlockItem("copper_grate", builder()));
- public static final Item EXPOSED_COPPER_GRATE = register(new BlockItem("exposed_copper_grate", builder()));
- public static final Item WEATHERED_COPPER_GRATE = register(new BlockItem("weathered_copper_grate", builder()));
- public static final Item OXIDIZED_COPPER_GRATE = register(new BlockItem("oxidized_copper_grate", builder()));
- public static final Item WAXED_COPPER_GRATE = register(new BlockItem("waxed_copper_grate", builder()));
- public static final Item WAXED_EXPOSED_COPPER_GRATE = register(new BlockItem("waxed_exposed_copper_grate", builder()));
- public static final Item WAXED_WEATHERED_COPPER_GRATE = register(new BlockItem("waxed_weathered_copper_grate", builder()));
- public static final Item WAXED_OXIDIZED_COPPER_GRATE = register(new BlockItem("waxed_oxidized_copper_grate", builder()));
- public static final Item COPPER_BULB = register(new BlockItem("copper_bulb", builder()));
- public static final Item EXPOSED_COPPER_BULB = register(new BlockItem("exposed_copper_bulb", builder()));
- public static final Item WEATHERED_COPPER_BULB = register(new BlockItem("weathered_copper_bulb", builder()));
- public static final Item OXIDIZED_COPPER_BULB = register(new BlockItem("oxidized_copper_bulb", builder()));
- public static final Item WAXED_COPPER_BULB = register(new BlockItem("waxed_copper_bulb", builder()));
- public static final Item WAXED_EXPOSED_COPPER_BULB = register(new BlockItem("waxed_exposed_copper_bulb", builder()));
- public static final Item WAXED_WEATHERED_COPPER_BULB = register(new BlockItem("waxed_weathered_copper_bulb", builder()));
- public static final Item WAXED_OXIDIZED_COPPER_BULB = register(new BlockItem("waxed_oxidized_copper_bulb", builder()));
- public static final Item TRIAL_SPAWNER = register(new BlockItem("trial_spawner", builder()));
+ public static final Item COPPER_GRATE = register(new BlockItem(builder(), Blocks.COPPER_GRATE));
+ public static final Item EXPOSED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_GRATE));
+ public static final Item WEATHERED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_GRATE));
+ public static final Item OXIDIZED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_GRATE));
+ public static final Item WAXED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_COPPER_GRATE));
+ public static final Item WAXED_EXPOSED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_GRATE));
+ public static final Item WAXED_WEATHERED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_GRATE));
+ public static final Item WAXED_OXIDIZED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_GRATE));
+ public static final Item COPPER_BULB = register(new BlockItem(builder(), Blocks.COPPER_BULB));
+ public static final Item EXPOSED_COPPER_BULB = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_BULB));
+ public static final Item WEATHERED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_BULB));
+ public static final Item OXIDIZED_COPPER_BULB = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_BULB));
+ public static final Item WAXED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_COPPER_BULB));
+ public static final Item WAXED_EXPOSED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_BULB));
+ public static final Item WAXED_WEATHERED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_BULB));
+ public static final Item WAXED_OXIDIZED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_BULB));
+ public static final Item TRIAL_SPAWNER = register(new BlockItem(builder(), Blocks.TRIAL_SPAWNER));
public static final Item TRIAL_KEY = register(new Item("trial_key", builder()));
public static final Item OMINOUS_TRIAL_KEY = register(new Item("ominous_trial_key", builder()));
- public static final Item VAULT = register(new BlockItem("vault", builder()));
+ public static final Item VAULT = register(new BlockItem(builder(), Blocks.VAULT));
public static final Item OMINOUS_BOTTLE = register(new Item("ominous_bottle", builder()));
public static final Item BREEZE_ROD = register(new Item("breeze_rod", builder()));
@@ -1377,11 +1376,7 @@ public final class Items {
public static T register(T item, int id) {
item.setJavaId(id);
- // This makes sure that the array is large enough to put the java item at the correct location
- if (Registries.JAVA_ITEMS.get().size() <= id) {
- Registries.JAVA_ITEMS.get().addAll(Collections.nCopies(id - Registries.JAVA_ITEMS.get().size() + 1, AIR));
- }
- Registries.JAVA_ITEMS.get().set(id, item);
+ Registries.JAVA_ITEMS.registerWithAnyIndex(id, item, AIR);
Registries.JAVA_ITEM_IDENTIFIERS.register(item.javaIdentifier(), item);
return item;
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java
index 6c2678db9..b53843882 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java
@@ -35,6 +35,7 @@ import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.inventory.item.BannerPattern;
import org.geysermc.geyser.inventory.item.DyeColor;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.registry.JavaRegistry;
@@ -199,8 +200,8 @@ public class BannerItem extends BlockItem {
return null;
}
- public BannerItem(String javaIdentifier, Builder builder) {
- super(javaIdentifier, builder);
+ public BannerItem(Builder builder, Block block, Block... otherBlocks) {
+ super(builder, block, otherBlocks);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java
index 0dbf0971a..30a31a100 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java
@@ -25,11 +25,26 @@
package org.geysermc.geyser.item.type;
-/**
- * TODO needed?
- */
+import org.geysermc.geyser.level.block.type.Block;
+
public class BlockItem extends Item {
- public BlockItem(String javaIdentifier, Builder builder) {
+ public BlockItem(Builder builder, Block block, Block... otherBlocks) {
+ super(block.javaIdentifier().value(), builder);
+
+ // Ensure this item can be looked up by its block(s)
+ registerBlock(block, this);
+ for (Block otherBlock : otherBlocks) {
+ registerBlock(otherBlock, this);
+ }
+ }
+
+ // Use this constructor if the item name is not the same as its primary block
+ public BlockItem(String javaIdentifier, Builder builder, Block block, Block... otherBlocks) {
super(javaIdentifier, builder);
+
+ registerBlock(block, this);
+ for (Block otherBlock : otherBlocks) {
+ registerBlock(otherBlock, this);
+ }
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java
index 2631bf9be..578ba4063 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/DecoratedPotItem.java
@@ -27,6 +27,7 @@ package org.geysermc.geyser.item.type;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtType;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
@@ -38,8 +39,8 @@ import java.util.List;
public class DecoratedPotItem extends BlockItem {
- public DecoratedPotItem(String javaIdentifier, Builder builder) {
- super(javaIdentifier, builder);
+ public DecoratedPotItem(Builder builder, Block block, Block... otherBlocks) {
+ super(builder, block, otherBlocks);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/Item.java b/core/src/main/java/org/geysermc/geyser/item/type/Item.java
index fc4fda07c..1ec410eaf 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/Item.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/Item.java
@@ -35,6 +35,7 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
@@ -49,20 +50,12 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Item {
- /**
- * This is a map from Java-only enchantments to their translation keys so that we can
- * map these enchantments to Bedrock clients, since they don't actually exist there.
- */
- private static final Map ENCHANTMENT_TRANSLATION_KEYS = Map.of(
- Enchantment.JavaEnchantment.SWEEPING_EDGE, "enchantment.minecraft.sweeping",
- Enchantment.JavaEnchantment.DENSITY, "enchantment.minecraft.density",
- Enchantment.JavaEnchantment.BREACH, "enchantment.minecraft.breach",
- Enchantment.JavaEnchantment.WIND_BURST, "enchantment.minecraft.wind_burst");
-
+ private static final Map BLOCK_TO_ITEM = new HashMap<>();
private final String javaIdentifier;
private int javaId = -1;
private final int stackSize;
@@ -233,6 +226,16 @@ public class Item {
// }
}
+ /**
+ * This is a map from Java-only enchantments to their translation keys so that we can
+ * map these enchantments to Bedrock clients, since they don't actually exist there.
+ */
+ private static final Map ENCHANTMENT_TRANSLATION_KEYS = Map.of(
+ Enchantment.JavaEnchantment.SWEEPING_EDGE, "enchantment.minecraft.sweeping",
+ Enchantment.JavaEnchantment.DENSITY, "enchantment.minecraft.density",
+ Enchantment.JavaEnchantment.BREACH, "enchantment.minecraft.breach",
+ Enchantment.JavaEnchantment.WIND_BURST, "enchantment.minecraft.wind_burst");
+
protected final @Nullable NbtMap remapEnchantment(GeyserSession session, int enchantId, int level, BedrockItemBuilder builder) {
// TODO verify
// TODO streamline Enchantment process
@@ -281,6 +284,18 @@ public class Item {
'}';
}
+ /**
+ * @return the block associated with this item, or air if nothing
+ */
+ @NonNull
+ public static Item byBlock(Block block) {
+ return BLOCK_TO_ITEM.getOrDefault(block, Items.AIR);
+ }
+
+ protected static void registerBlock(Block block, Item item) {
+ BLOCK_TO_ITEM.put(block, item);
+ }
+
public static Builder builder() {
return new Builder();
}
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java
index 0cdbe70f1..86572d60c 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/PlayerHeadItem.java
@@ -27,6 +27,7 @@ package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.auth.data.GameProfile;
import org.checkerframework.checker.nullness.qual.NonNull;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.MinecraftLocale;
@@ -34,9 +35,9 @@ import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-public class PlayerHeadItem extends Item {
- public PlayerHeadItem(String javaIdentifier, Builder builder) {
- super(javaIdentifier, builder);
+public class PlayerHeadItem extends BlockItem {
+ public PlayerHeadItem(Builder builder, Block block, Block... otherBlocks) {
+ super(builder, block, otherBlocks);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java
index 6b2d589d6..a539fa739 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/ShulkerBoxItem.java
@@ -30,6 +30,7 @@ import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
@@ -42,8 +43,8 @@ import java.util.ArrayList;
import java.util.List;
public class ShulkerBoxItem extends BlockItem {
- public ShulkerBoxItem(String javaIdentifier, Builder builder) {
- super(javaIdentifier, builder);
+ public ShulkerBoxItem(Builder builder, Block block, Block... otherBlocks) {
+ super(builder, block, otherBlocks);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java
index 85291886e..db33bb584 100644
--- a/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java
+++ b/core/src/main/java/org/geysermc/geyser/item/type/TippedArrowItem.java
@@ -41,16 +41,18 @@ public class TippedArrowItem extends ArrowItem {
@Override
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
- PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
- if (potionContents != null) {
- TippedArrowPotion tippedArrowPotion = TippedArrowPotion.of(potionContents.getPotionId());
- if (tippedArrowPotion != null) {
- return ItemData.builder()
- .definition(mapping.getBedrockDefinition())
- .damage(tippedArrowPotion.getBedrockId())
- .count(count);
+ if (components != null) {
+ PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
+ if (potionContents != null) {
+ TippedArrowPotion tippedArrowPotion = TippedArrowPotion.of(potionContents.getPotionId());
+ if (tippedArrowPotion != null) {
+ return ItemData.builder()
+ .definition(mapping.getBedrockDefinition())
+ .damage(tippedArrowPotion.getBedrockId())
+ .count(count);
+ }
+ GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionContents.getPotionId());
}
- GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionContents.getPotionId());
}
return super.translateToBedrock(count, components, mapping, mappings);
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java
index 08611a5e1..9faa7424c 100644
--- a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java
+++ b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java
@@ -25,24 +25,20 @@
package org.geysermc.geyser.level;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i;
-import org.cloudburstmc.nbt.NbtMap;
-import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.erosion.packet.backendbound.*;
+import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket;
+import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket;
+import org.geysermc.erosion.packet.backendbound.BackendboundPickBlockPacket;
import org.geysermc.erosion.util.BlockPositionIterator;
-import org.geysermc.erosion.util.LecternUtils;
import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.util.BlockEntityUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
-import java.util.List;
import java.util.concurrent.CompletableFuture;
public class GeyserWorldManager extends WorldManager {
@@ -91,51 +87,6 @@ public class GeyserWorldManager extends WorldManager {
return false;
}
- @Override
- public void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos) {
- var erosionHandler = session.getErosionHandler().getAsActive();
- if (erosionHandler == null) {
- // No-op - don't send any additional information other than what the chunk has already sent
- return;
- }
- List vectors = new ObjectArrayList<>(blockEntityInfos.size());
- //noinspection ForLoopReplaceableByForEach - avoid constructing iterator
- for (int i = 0; i < blockEntityInfos.size(); i++) {
- BlockEntityInfo info = blockEntityInfos.get(i);
- vectors.add(Vector3i.from(info.getX(), info.getY(), info.getZ()));
- }
- erosionHandler.sendPacket(new BackendboundBatchBlockEntityPacket(x, z, vectors));
- }
-
- @Override
- public void sendLecternData(GeyserSession session, int x, int y, int z) {
- var erosionHandler = session.getErosionHandler().getAsActive();
- if (erosionHandler != null) {
- erosionHandler.sendPacket(new BackendboundBlockEntityPacket(Vector3i.from(x, y, z)));
- return;
- }
-
- // Without direct server access, we can't get lectern information on-the-fly.
- // I should have set this up so it's only called when there is a book in the block state. - Camotoy
- NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(x, y, z, 1);
- lecternTag.putCompound("book", NbtMap.builder()
- .putByte("Count", (byte) 1)
- .putShort("Damage", (short) 0)
- .putString("Name", "minecraft:written_book")
- .putCompound("tag", NbtMap.builder()
- .putString("photoname", "")
- .putString("text", "")
- .build())
- .build());
- lecternTag.putInt("page", -1); // I'm surprisingly glad this exists - it forces Bedrock to stop reading immediately. Usually.
- BlockEntityUtils.updateBlockEntity(session, lecternTag.build(), Vector3i.from(x, y, z));
- }
-
- @Override
- public boolean shouldExpectLecternHandled(GeyserSession session) {
- return session.getErosionHandler().isActive();
- }
-
@Override
public void setGameRule(GeyserSession session, String name, Object value) {
super.setGameRule(session, name, value);
@@ -179,9 +130,9 @@ public class GeyserWorldManager extends WorldManager {
if (erosionHandler == null) {
return super.getPickItemComponents(session, x, y, z, addNbtData);
}
- CompletableFuture future = new CompletableFuture<>();
+ CompletableFuture> future = new CompletableFuture<>();
erosionHandler.setPickBlockLookup(future);
erosionHandler.sendPacket(new BackendboundPickBlockPacket(Vector3i.from(x, y, z)));
- return future;
+ return future.thenApply(RAW_TRANSFORMER);
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java
index a1b16a1d5..3670b6b73 100644
--- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java
+++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java
@@ -25,19 +25,28 @@
package org.geysermc.geyser.level;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.erosion.util.BlockPositionIterator;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponent;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemCodecHelper;
import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty;
-import java.util.List;
+import java.util.HashMap;
import java.util.Locale;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
+import java.util.function.Function;
/**
* Class that manages or retrieves various information
@@ -48,6 +57,16 @@ import java.util.concurrent.CompletableFuture;
*/
public abstract class WorldManager {
+ @NonNull
+ public final BlockState blockAt(GeyserSession session, Vector3i vector) {
+ return this.blockAt(session, vector.getX(), vector.getY(), vector.getZ());
+ }
+
+ @NonNull
+ public BlockState blockAt(GeyserSession session, int x, int y, int z) {
+ return BlockState.of(this.getBlockAt(session, x, y, z));
+ }
+
/**
* Gets the Java block state at the specified location
*
@@ -97,40 +116,6 @@ public abstract class WorldManager {
*/
public abstract boolean hasOwnChunkCache();
- /**
- * Sigh.
- *
- * So, on Java Edition, the lectern is an inventory. Java opens it and gets the contents of the book there.
- * On Bedrock, the lectern contents are part of the block entity tag. Therefore, Bedrock expects to have the contents
- * of the lectern ready and present in the world. If the contents are not there, it takes at least two clicks for the
- * lectern to update the tag and then present itself.
- *
- * We solve this problem by querying all loaded lecterns, where possible, and sending their information in a block entity
- * tag.
- *
- * Note that the lectern data may be sent asynchronously.
- *
- * @param session the session of the player
- * @param x the x coordinate of the lectern
- * @param y the y coordinate of the lectern
- * @param z the z coordinate of the lectern
- */
- public abstract void sendLecternData(GeyserSession session, int x, int y, int z);
-
- /**
- * {@link #sendLecternData(GeyserSession, int, int, int)} but batched for chunks.
- *
- * @param x chunk x
- * @param z chunk z
- * @param blockEntityInfos a list of coordinates (chunk local) to grab lecterns from.
- */
- public abstract void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos);
-
- /**
- * @return whether we should expect lectern data to update, or if we have to fall back on a workaround.
- */
- public abstract boolean shouldExpectLecternHandled(GeyserSession session);
-
/**
* Updates a gamerule value on the Java server
*
@@ -223,4 +208,20 @@ public abstract class WorldManager {
public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addExtraData) {
return CompletableFuture.completedFuture(null);
}
+
+ protected static final Function, DataComponents> RAW_TRANSFORMER = map -> {
+ try {
+ Map, DataComponent, ?>> components = new HashMap<>();
+ Int2ObjectMaps.fastForEach(map, entry -> {
+ DataComponentType type = DataComponentType.from(entry.getIntKey());
+ ByteBuf buf = Unpooled.wrappedBuffer(entry.getValue());
+ DataComponent value = type.readDataComponent(ItemCodecHelper.INSTANCE, buf);
+ components.put(type, value);
+ });
+ return new DataComponents(components);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ };
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
index 52759c709..01e95fc7a 100644
--- a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
+++ b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java
@@ -25,363 +25,19 @@
package org.geysermc.geyser.level.block;
-import com.fasterxml.jackson.databind.JsonNode;
-import it.unimi.dsi.fastutil.ints.*;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
-import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
-import org.geysermc.geyser.level.physics.Direction;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.block.type.PistonBlock;
import org.geysermc.geyser.level.physics.PistonBehavior;
import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.BlockMapping;
-import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntityTranslator;
-import org.geysermc.geyser.util.collection.FixedInt2ByteMap;
-import org.geysermc.geyser.util.collection.FixedInt2IntMap;
-import org.geysermc.geyser.util.collection.LecternHasBookMap;
-
-import java.util.Locale;
/**
* Used for block entities if the Java block state contains Bedrock block information.
*/
public final class BlockStateValues {
- private static final IntSet ALL_CAULDRONS = new IntOpenHashSet();
- private static final Int2IntMap BANNER_COLORS = new FixedInt2IntMap();
- private static final Int2ByteMap BED_COLORS = new FixedInt2ByteMap();
- private static final Int2IntMap BRUSH_PROGRESS = new Int2IntOpenHashMap();
- private static final Int2ByteMap COMMAND_BLOCK_VALUES = new Int2ByteOpenHashMap();
- private static final Int2ObjectMap DOUBLE_CHEST_VALUES = new Int2ObjectOpenHashMap<>();
- private static final Int2ObjectMap FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>();
- private static final IntSet HORIZONTAL_FACING_JIGSAWS = new IntOpenHashSet();
- private static final LecternHasBookMap LECTERN_BOOK_STATES = new LecternHasBookMap();
- private static final IntSet NON_WATER_CAULDRONS = new IntOpenHashSet();
- private static final Int2IntMap NOTEBLOCK_PITCHES = new FixedInt2IntMap();
- private static final Int2BooleanMap PISTON_VALUES = new Int2BooleanOpenHashMap();
- private static final IntSet STICKY_PISTONS = new IntOpenHashSet();
- private static final Object2IntMap PISTON_HEADS = new Object2IntOpenHashMap<>();
- private static final Int2ObjectMap PISTON_ORIENTATION = new Int2ObjectOpenHashMap<>();
- private static final IntSet ALL_PISTON_HEADS = new IntOpenHashSet();
- private static final IntSet MOVING_PISTONS = new IntOpenHashSet();
- private static final Int2ByteMap SKULL_VARIANTS = new FixedInt2ByteMap();
- private static final IntSet SKULL_POWERED = new IntOpenHashSet();
- private static final Int2ByteMap SKULL_ROTATIONS = new Int2ByteOpenHashMap();
- private static final Int2IntMap SKULL_WALL_DIRECTIONS = new Int2IntOpenHashMap();
- private static final Int2ByteMap SHULKERBOX_DIRECTIONS = new FixedInt2ByteMap();
- private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap();
- private static final IntSet UPPER_DOORS = new IntOpenHashSet();
-
- public static final int JAVA_AIR_ID = 0;
-
- public static int JAVA_COBWEB_ID;
- public static int JAVA_FURNACE_ID;
- public static int JAVA_FURNACE_LIT_ID;
- public static int JAVA_HONEY_BLOCK_ID;
- public static int JAVA_SLIME_BLOCK_ID;
- public static int JAVA_SPAWNER_ID;
- public static int JAVA_WATER_ID;
-
public static final int NUM_WATER_LEVELS = 9;
- /**
- * Determines if the block state contains Bedrock block information
- *
- * @param javaId The Java Identifier of the block
- * @param javaBlockState the Java Block State of the block
- * @param blockData JsonNode of info about the block from blocks.json
- */
- public static void storeBlockStateValues(String javaId, int javaBlockState, JsonNode blockData) {
- JsonNode bannerColor = blockData.get("banner_color");
- if (bannerColor != null) {
- BANNER_COLORS.put(javaBlockState, (byte) bannerColor.intValue());
- return; // There will never be a banner color and a skull variant
- }
-
- JsonNode bedColor = blockData.get("bed_color");
- if (bedColor != null) {
- BED_COLORS.put(javaBlockState, (byte) bedColor.intValue());
- return;
- }
-
- JsonNode bedrockStates = blockData.get("bedrock_states");
- if (bedrockStates != null) {
- JsonNode brushedProgress = bedrockStates.get("brushed_progress");
- if (brushedProgress != null) {
- BRUSH_PROGRESS.put(javaBlockState, brushedProgress.intValue());
- return;
- }
- }
-
- if (javaId.contains("command_block")) {
- COMMAND_BLOCK_VALUES.put(javaBlockState, javaId.contains("conditional=true") ? (byte) 1 : (byte) 0);
- return;
- }
-
- if (blockData.get("double_chest_position") != null) {
- boolean isX = (blockData.get("x") != null);
- boolean isDirectionPositive = ((blockData.get("x") != null && blockData.get("x").asBoolean()) ||
- (blockData.get("z") != null && blockData.get("z").asBoolean()));
- boolean isLeft = (blockData.get("double_chest_position").asText().contains("left"));
- DOUBLE_CHEST_VALUES.put(javaBlockState, new DoubleChestValue(isX, isDirectionPositive, isLeft));
- return;
- }
-
- if (javaId.startsWith("minecraft:potted_") || javaId.equals("minecraft:flower_pot")) {
- String name = javaId.replace("potted_", "");
- if (name.contains("azalea")) {
- // Exception to the rule
- name = name.replace("_bush", "");
- }
- FLOWER_POT_VALUES.put(javaBlockState, name);
- return;
- }
-
- if (javaId.startsWith("minecraft:lectern")) {
- LECTERN_BOOK_STATES.put(javaBlockState, javaId.contains("has_book=true"));
- return;
- }
-
- JsonNode notePitch = blockData.get("note_pitch");
- if (notePitch != null) {
- NOTEBLOCK_PITCHES.put(javaBlockState, blockData.get("note_pitch").intValue());
- return;
- }
-
- if (javaId.contains("piston[")) { // minecraft:moving_piston, minecraft:sticky_piston, minecraft:piston
- if (javaId.startsWith("minecraft:moving_piston")) {
- MOVING_PISTONS.add(javaBlockState);
- } else {
- PISTON_VALUES.put(javaBlockState, javaId.contains("extended=true"));
- }
- if (javaId.contains("sticky")) {
- STICKY_PISTONS.add(javaBlockState);
- }
- PISTON_ORIENTATION.put(javaBlockState, getBlockDirection(javaId));
- return;
- } else if (javaId.startsWith("minecraft:piston_head")) {
- ALL_PISTON_HEADS.add(javaBlockState);
- if (javaId.contains("short=false")) {
- PISTON_HEADS.put(getBlockDirection(javaId), javaBlockState);
- }
- return;
- }
-
- JsonNode skullVariation = blockData.get("variation");
- if (skullVariation != null) {
- SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue());
- }
-
- JsonNode skullRotation = blockData.get("skull_rotation");
- if (skullRotation != null) {
- SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue());
- }
-
- if (javaId.startsWith("minecraft:dragon_head[") || javaId.startsWith("minecraft:piglin_head[")
- || javaId.startsWith("minecraft:dragon_wall_head[") || javaId.startsWith("minecraft:piglin_wall_head[")) {
- if (javaId.contains("powered=true")) {
- SKULL_POWERED.add(javaBlockState);
- }
- }
-
- if (javaId.contains("wall_skull") || javaId.contains("wall_head")) {
- String direction = javaId.substring(javaId.lastIndexOf("facing=") + 7, javaId.lastIndexOf("powered=") - 1);
- int rotation = switch (direction) {
- case "north" -> 180;
- case "west" -> 90;
- case "east" -> 270;
- default -> 0; // Also south
- };
- SKULL_WALL_DIRECTIONS.put(javaBlockState, rotation);
- }
-
- JsonNode shulkerDirection = blockData.get("shulker_direction");
- if (shulkerDirection != null) {
- BlockStateValues.SHULKERBOX_DIRECTIONS.put(javaBlockState, (byte) shulkerDirection.intValue());
- return;
- }
-
- if (javaId.startsWith("minecraft:water") && !javaId.contains("cauldron")) {
- String strLevel = javaId.substring(javaId.lastIndexOf("level=") + 6, javaId.length() - 1);
- int level = Integer.parseInt(strLevel);
- WATER_LEVEL.put(javaBlockState, level);
- return;
- }
-
- if (javaId.startsWith("minecraft:jigsaw[orientation=")) {
- String blockStateData = javaId.substring(javaId.indexOf("orientation=") + "orientation=".length(), javaId.lastIndexOf('_'));
- Direction direction = Direction.valueOf(blockStateData.toUpperCase(Locale.ROOT));
- if (direction.isHorizontal()) {
- HORIZONTAL_FACING_JIGSAWS.add(javaBlockState);
- }
- return;
- }
-
- if (javaId.contains("cauldron")) {
- ALL_CAULDRONS.add(javaBlockState);
- }
- if (javaId.contains("_cauldron") && !javaId.contains("water_")) {
- NON_WATER_CAULDRONS.add(javaBlockState);
- }
-
- if (javaId.contains("_door[") && javaId.contains("half=upper")) {
- UPPER_DOORS.add(javaBlockState);
- }
- }
-
- /**
- * Banner colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives an integer color that Bedrock can use.
- *
- * @param state BlockState of the block
- * @return Banner color integer or -1 if no color
- */
- public static int getBannerColor(int state) {
- return BANNER_COLORS.getOrDefault(state, -1);
- }
-
- /**
- * Bed colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives a byte color that Bedrock can use - Bedrock needs a byte in the final tag.
- *
- * @param state BlockState of the block
- * @return Bed color byte or -1 if no color
- */
- public static byte getBedColor(int state) {
- return BED_COLORS.getOrDefault(state, (byte) -1);
- }
-
- /**
- * The brush progress of suspicious sand/gravel is not sent by the java server when it updates the block entity.
- * Although brush progress is part of the bedrock block state, it must be included in the block entity update.
- *
- * @param state BlockState of the block
- * @return brush progress or 0 if the lookup failed
- */
- public static int getBrushProgress(int state) {
- return BRUSH_PROGRESS.getOrDefault(state, 0);
- }
-
- /**
- * @return if this Java block state is a non-empty non-water cauldron
- */
- public static boolean isNonWaterCauldron(int state) {
- return NON_WATER_CAULDRONS.contains(state);
- }
-
- /**
- * Cauldrons (since Bedrock 1.18.30) must have a block entity packet sent on chunk load to fix rendering issues.
- *
- * When using a bucket on a cauldron sending a ServerboundUseItemPacket can result in the liquid being placed.
- *
- * @return if this Java block state is a cauldron
- */
- public static boolean isCauldron(int state) {
- return ALL_CAULDRONS.contains(state);
- }
-
- /**
- * The block state in Java and Bedrock both contain the conditional bit, however command block block entity tags
- * in Bedrock need the conditional information.
- *
- * @return the list of all command blocks and if they are conditional (1 or 0)
- */
- public static Int2ByteMap getCommandBlockValues() {
- return COMMAND_BLOCK_VALUES;
- }
-
- /**
- * All double chest values are part of the block state in Java and part of the block entity tag in Bedrock.
- * This gives the DoubleChestValue that can be calculated into the final tag.
- *
- * @return The map of all DoubleChestValues.
- */
- public static Int2ObjectMap getDoubleChestValues() {
- return DOUBLE_CHEST_VALUES;
- }
-
- /**
- * Get the Int2ObjectMap of flower pot block states to containing plant
- *
- * @return Int2ObjectMap of flower pot values
- */
- public static Int2ObjectMap getFlowerPotValues() {
- return FLOWER_POT_VALUES;
- }
-
- /**
- * @return a set of all forward-facing jigsaws, to use as a fallback if NBT is missing.
- */
- public static IntSet getHorizontalFacingJigsaws() {
- return HORIZONTAL_FACING_JIGSAWS;
- }
-
- /**
- * @return the lectern book state map pointing to book present state
- */
- public static LecternHasBookMap getLecternBookStates() {
- return LECTERN_BOOK_STATES;
- }
-
- /**
- * The note that noteblocks output when hit is part of the block state in Java but sent as a BlockEventPacket in Bedrock.
- * This gives an integer pitch that Bedrock can use.
- *
- * @param state BlockState of the block
- * @return note block note integer or -1 if not present
- */
- public static int getNoteblockPitch(int state) {
- return NOTEBLOCK_PITCHES.getOrDefault(state, -1);
- }
-
- /**
- * Get the Int2BooleanMap showing if a piston block state is extended or not.
- *
- * @return the Int2BooleanMap of piston extensions.
- */
- public static Int2BooleanMap getPistonValues() {
- return PISTON_VALUES;
- }
-
- public static boolean isStickyPiston(int blockState) {
- return STICKY_PISTONS.contains(blockState);
- }
-
- public static boolean isPistonHead(int state) {
- return ALL_PISTON_HEADS.contains(state);
- }
-
- /**
- * Get the Java Block State for a piston head for a specific direction
- * This is used in PistonBlockEntity to get the BlockCollision for the piston head.
- *
- * @param direction Direction the piston head points in
- * @return Block state for the piston head
- */
- public static int getPistonHead(Direction direction) {
- return PISTON_HEADS.getOrDefault(direction, BlockStateValues.JAVA_AIR_ID);
- }
-
- /**
- * Check if a block is a minecraft:moving_piston
- * This is used in ChunkUtils to prevent them from being placed as it causes
- * pistons to flicker and it is not needed
- *
- * @param state Block state of the block
- * @return True if the block is a moving_piston
- */
- public static boolean isMovingPiston(int state) {
- return MOVING_PISTONS.contains(state);
- }
-
- /**
- * This is used in GeyserPistonEvents.java and accepts minecraft:piston,
- * minecraft:sticky_piston, and minecraft:moving_piston.
- *
- * @param state The block state of the piston base
- * @return The direction in which the piston faces
- */
- public static Direction getPistonOrientation(int state) {
- return PISTON_ORIENTATION.get(state);
- }
-
/**
* Checks if a block sticks to other blocks
* (Slime and honey blocks)
@@ -389,8 +45,9 @@ public final class BlockStateValues {
* @param state The block state
* @return True if the block sticks to adjacent blocks
*/
- public static boolean isBlockSticky(int state) {
- return state == JAVA_SLIME_BLOCK_ID || state == JAVA_HONEY_BLOCK_ID;
+ public static boolean isBlockSticky(BlockState state) {
+ Block block = state.block();
+ return block == Blocks.SLIME_BLOCK || block == Blocks.HONEY_BLOCK;
}
/**
@@ -400,13 +57,13 @@ public final class BlockStateValues {
* @param stateB The block state of block b
* @return True if the blocks are attached to each other
*/
- public static boolean isBlockAttached(int stateA, int stateB) {
+ public static boolean isBlockAttached(BlockState stateA, BlockState stateB) {
boolean aSticky = isBlockSticky(stateA);
boolean bSticky = isBlockSticky(stateB);
if (aSticky && bSticky) {
// Only matching sticky blocks are attached together
// Honey + Honey & Slime + Slime
- return stateA == stateB;
+ return stateA.block() == stateB.block();
}
return aSticky || bSticky;
}
@@ -415,84 +72,33 @@ public final class BlockStateValues {
* @param state The block state of the block
* @return true if a piston can break the block
*/
- public static boolean canPistonDestroyBlock(int state) {
- return BlockRegistries.JAVA_BLOCKS.getOrDefault(state, BlockMapping.DEFAULT).getPistonBehavior() == PistonBehavior.DESTROY;
+ public static boolean canPistonDestroyBlock(BlockState state) {
+ return state.block().pushReaction() == PistonBehavior.DESTROY;
}
- public static boolean canPistonMoveBlock(int javaId, boolean isPushing) {
- if (javaId == JAVA_AIR_ID) {
+ public static boolean canPistonMoveBlock(BlockState state, boolean isPushing) {
+ Block block = state.block();
+ if (block == Blocks.AIR) {
return true;
}
- // Pistons can only be moved if they aren't extended
- if (PistonBlockEntityTranslator.isBlock(javaId)) {
- return !PISTON_VALUES.get(javaId);
- }
- BlockMapping block = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaId, BlockMapping.DEFAULT);
- // Bedrock, End portal frames, etc. can't be moved
- if (block.getHardness() == -1.0d) {
+ if (block == Blocks.OBSIDIAN || block == Blocks.CRYING_OBSIDIAN || block == Blocks.RESPAWN_ANCHOR || block == Blocks.REINFORCED_DEEPSLATE) { // Hardcoded as of 1.20.5
return false;
}
- return switch (block.getPistonBehavior()) {
+ // Pistons can only be moved if they aren't extended
+ if (block instanceof PistonBlock) {
+ return !state.getValue(Properties.EXTENDED);
+ }
+ // Bedrock, End portal frames, etc. can't be moved
+ if (block.destroyTime() == -1.0f) {
+ return false;
+ }
+ return switch (block.pushReaction()) {
case BLOCK, DESTROY -> false;
case PUSH_ONLY -> isPushing; // Glazed terracotta can only be pushed
- default -> !block.isBlockEntity(); // Pistons can't move block entities
+ default -> !block.hasBlockEntity(); // Pistons can't move block entities
};
}
- /**
- * Skull variations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives a byte variant ID that Bedrock can use.
- *
- * @param state BlockState of the block
- * @return Skull variant byte or -1 if no variant
- */
- public static byte getSkullVariant(int state) {
- return SKULL_VARIANTS.getOrDefault(state, (byte) -1);
- }
-
- /**
- * Skull rotations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives a byte rotation that Bedrock can use.
- *
- * @param state BlockState of the block
- * @return Skull rotation value or -1 if no value
- */
- public static byte getSkullRotation(int state) {
- return SKULL_ROTATIONS.getOrDefault(state, (byte) -1);
- }
-
- /**
- * As of Java 1.20.2:
- * Skull powered states are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- *
- * @param state BlockState of the block
- * @return true if this skull is currently being powered.
- */
- public static boolean isSkullPowered(int state) {
- return SKULL_POWERED.contains(state);
- }
-
- /**
- * Skull rotations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives a integer rotation that Bedrock can use.
- *
- * @return Skull wall rotation value with the blockstate
- */
- public static Int2IntMap getSkullWallDirections() {
- return SKULL_WALL_DIRECTIONS;
- }
-
- /**
- * Shulker box directions are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
- * This gives a byte direction that Bedrock can use.
- *
- * @param state BlockState of the block
- * @return Shulker direction value or -1 if no value
- */
- public static byte getShulkerBoxDirection(int state) {
- return SHULKERBOX_DIRECTIONS.getOrDefault(state, (byte) -1);
- }
-
/**
* Get the level of water from the block state.
*
@@ -500,17 +106,11 @@ public final class BlockStateValues {
* @return The water level or -1 if the block isn't water
*/
public static int getWaterLevel(int state) {
- return WATER_LEVEL.getOrDefault(state, -1);
- }
-
- /**
- * Check if a block is the upper half of a door.
- *
- * @param state BlockState of the block
- * @return True if the block is the upper half of a door
- */
- public static boolean isUpperDoor(int state) {
- return UPPER_DOORS.contains(state);
+ BlockState blockState = BlockState.of(state);
+ if (!blockState.is(Blocks.WATER)) {
+ return -1;
+ }
+ return blockState.getValue(Properties.LEVEL);
}
/**
@@ -544,31 +144,18 @@ public final class BlockStateValues {
* @param state BlockState of the block
* @return The block's slipperiness
*/
- public static float getSlipperiness(int state) {
- String blockIdentifier = BlockRegistries.JAVA_BLOCKS.getOrDefault(state, BlockMapping.DEFAULT).getJavaIdentifier();
- return switch (blockIdentifier) {
- case "minecraft:slime_block" -> 0.8f;
- case "minecraft:ice", "minecraft:packed_ice" -> 0.98f;
- case "minecraft:blue_ice" -> 0.989f;
- default -> 0.6f;
- };
- }
-
- private static Direction getBlockDirection(String javaId) {
- if (javaId.contains("down")) {
- return Direction.DOWN;
- } else if (javaId.contains("up")) {
- return Direction.UP;
- } else if (javaId.contains("south")) {
- return Direction.SOUTH;
- } else if (javaId.contains("west")) {
- return Direction.WEST;
- } else if (javaId.contains("north")) {
- return Direction.NORTH;
- } else if (javaId.contains("east")) {
- return Direction.EAST;
+ public static float getSlipperiness(BlockState state) {
+ Block block = state.block();
+ if (block == Blocks.SLIME_BLOCK) {
+ return 0.8f;
}
- throw new IllegalStateException();
+ if (block == Blocks.ICE || block == Blocks.PACKED_ICE) {
+ return 0.98f;
+ }
+ if (block == Blocks.BLUE_ICE) {
+ return 0.989f;
+ }
+ return 0.6f;
}
private BlockStateValues() {
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java
new file mode 100644
index 000000000..857a3fc13
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java
@@ -0,0 +1,2823 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block;
+
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.level.block.property.ChestType;
+import org.geysermc.geyser.level.block.property.FrontAndTop;
+import org.geysermc.geyser.level.block.type.*;
+import org.geysermc.geyser.level.physics.Axis;
+import org.geysermc.geyser.level.physics.Direction;
+import org.geysermc.geyser.level.physics.PistonBehavior;
+import org.geysermc.geyser.registry.BlockRegistries;
+
+import static org.geysermc.geyser.level.block.property.Properties.*;
+import static org.geysermc.geyser.level.block.type.Block.builder;
+
+@SuppressWarnings("unused")
+public final class Blocks {
+ public static final Block AIR = register(new Block("air", builder()));
+ public static final Block STONE = register(new Block("stone", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block GRANITE = register(new Block("granite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_GRANITE = register(new Block("polished_granite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DIORITE = register(new Block("diorite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_DIORITE = register(new Block("polished_diorite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block ANDESITE = register(new Block("andesite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_ANDESITE = register(new Block("polished_andesite", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block GRASS_BLOCK = register(new Block("grass_block", builder().destroyTime(0.6f)
+ .booleanState(SNOWY)));
+ public static final Block DIRT = register(new Block("dirt", builder().destroyTime(0.5f)));
+ public static final Block COARSE_DIRT = register(new Block("coarse_dirt", builder().destroyTime(0.5f)));
+ public static final Block PODZOL = register(new Block("podzol", builder().destroyTime(0.5f)
+ .booleanState(SNOWY)));
+ public static final Block COBBLESTONE = register(new Block("cobblestone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block OAK_PLANKS = register(new Block("oak_planks", builder().destroyTime(2.0f)));
+ public static final Block SPRUCE_PLANKS = register(new Block("spruce_planks", builder().destroyTime(2.0f)));
+ public static final Block BIRCH_PLANKS = register(new Block("birch_planks", builder().destroyTime(2.0f)));
+ public static final Block JUNGLE_PLANKS = register(new Block("jungle_planks", builder().destroyTime(2.0f)));
+ public static final Block ACACIA_PLANKS = register(new Block("acacia_planks", builder().destroyTime(2.0f)));
+ public static final Block CHERRY_PLANKS = register(new Block("cherry_planks", builder().destroyTime(2.0f)));
+ public static final Block DARK_OAK_PLANKS = register(new Block("dark_oak_planks", builder().destroyTime(2.0f)));
+ public static final Block MANGROVE_PLANKS = register(new Block("mangrove_planks", builder().destroyTime(2.0f)));
+ public static final Block BAMBOO_PLANKS = register(new Block("bamboo_planks", builder().destroyTime(2.0f)));
+ public static final Block BAMBOO_MOSAIC = register(new Block("bamboo_mosaic", builder().destroyTime(2.0f)));
+ public static final Block OAK_SAPLING = register(new Block("oak_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block SPRUCE_SAPLING = register(new Block("spruce_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block BIRCH_SAPLING = register(new Block("birch_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block JUNGLE_SAPLING = register(new Block("jungle_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block ACACIA_SAPLING = register(new Block("acacia_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block CHERRY_SAPLING = register(new Block("cherry_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block DARK_OAK_SAPLING = register(new Block("dark_oak_sapling", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(STAGE)));
+ public static final Block MANGROVE_PROPAGULE = register(new Block("mangrove_propagule", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_4)
+ .booleanState(HANGING)
+ .intState(STAGE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BEDROCK = register(new Block("bedrock", builder().destroyTime(-1.0f)));
+ public static final Block WATER = register(new WaterBlock("water", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY)
+ .intState(LEVEL)));
+ public static final Block LAVA = register(new Block("lava", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY)
+ .intState(LEVEL)));
+ public static final Block SAND = register(new Block("sand", builder().destroyTime(0.5f)));
+ public static final Block SUSPICIOUS_SAND = register(new Block("suspicious_sand", builder().setBlockEntity().destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DUSTED)));
+ public static final Block RED_SAND = register(new Block("red_sand", builder().destroyTime(0.5f)));
+ public static final Block GRAVEL = register(new Block("gravel", builder().destroyTime(0.6f)));
+ public static final Block SUSPICIOUS_GRAVEL = register(new Block("suspicious_gravel", builder().setBlockEntity().destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DUSTED)));
+ public static final Block GOLD_ORE = register(new Block("gold_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_GOLD_ORE = register(new Block("deepslate_gold_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block IRON_ORE = register(new Block("iron_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_IRON_ORE = register(new Block("deepslate_iron_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block COAL_ORE = register(new Block("coal_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_COAL_ORE = register(new Block("deepslate_coal_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block NETHER_GOLD_ORE = register(new Block("nether_gold_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block OAK_LOG = register(new Block("oak_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block SPRUCE_LOG = register(new Block("spruce_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block BIRCH_LOG = register(new Block("birch_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block JUNGLE_LOG = register(new Block("jungle_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block ACACIA_LOG = register(new Block("acacia_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block CHERRY_LOG = register(new Block("cherry_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block DARK_OAK_LOG = register(new Block("dark_oak_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block MANGROVE_LOG = register(new Block("mangrove_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block MANGROVE_ROOTS = register(new Block("mangrove_roots", builder().destroyTime(0.7f)
+ .booleanState(WATERLOGGED)));
+ public static final Block MUDDY_MANGROVE_ROOTS = register(new Block("muddy_mangrove_roots", builder().destroyTime(0.7f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block BAMBOO_BLOCK = register(new Block("bamboo_block", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_SPRUCE_LOG = register(new Block("stripped_spruce_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_BIRCH_LOG = register(new Block("stripped_birch_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_JUNGLE_LOG = register(new Block("stripped_jungle_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_ACACIA_LOG = register(new Block("stripped_acacia_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_CHERRY_LOG = register(new Block("stripped_cherry_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_DARK_OAK_LOG = register(new Block("stripped_dark_oak_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_OAK_LOG = register(new Block("stripped_oak_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_MANGROVE_LOG = register(new Block("stripped_mangrove_log", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_BAMBOO_BLOCK = register(new Block("stripped_bamboo_block", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block OAK_WOOD = register(new Block("oak_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block SPRUCE_WOOD = register(new Block("spruce_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block BIRCH_WOOD = register(new Block("birch_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block JUNGLE_WOOD = register(new Block("jungle_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block ACACIA_WOOD = register(new Block("acacia_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block CHERRY_WOOD = register(new Block("cherry_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block DARK_OAK_WOOD = register(new Block("dark_oak_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block MANGROVE_WOOD = register(new Block("mangrove_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_OAK_WOOD = register(new Block("stripped_oak_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_SPRUCE_WOOD = register(new Block("stripped_spruce_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_BIRCH_WOOD = register(new Block("stripped_birch_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_JUNGLE_WOOD = register(new Block("stripped_jungle_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_ACACIA_WOOD = register(new Block("stripped_acacia_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_CHERRY_WOOD = register(new Block("stripped_cherry_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_DARK_OAK_WOOD = register(new Block("stripped_dark_oak_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_MANGROVE_WOOD = register(new Block("stripped_mangrove_wood", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block OAK_LEAVES = register(new Block("oak_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_LEAVES = register(new Block("spruce_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_LEAVES = register(new Block("birch_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_LEAVES = register(new Block("jungle_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_LEAVES = register(new Block("acacia_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_LEAVES = register(new Block("cherry_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_LEAVES = register(new Block("dark_oak_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_LEAVES = register(new Block("mangrove_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block AZALEA_LEAVES = register(new Block("azalea_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block FLOWERING_AZALEA_LEAVES = register(new Block("flowering_azalea_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(DISTANCE)
+ .booleanState(PERSISTENT)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPONGE = register(new Block("sponge", builder().destroyTime(0.6f)));
+ public static final Block WET_SPONGE = register(new Block("wet_sponge", builder().destroyTime(0.6f)));
+ public static final Block GLASS = register(new Block("glass", builder().destroyTime(0.3f)));
+ public static final Block LAPIS_ORE = register(new Block("lapis_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_LAPIS_ORE = register(new Block("deepslate_lapis_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block LAPIS_BLOCK = register(new Block("lapis_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DISPENSER = register(new Block("dispenser", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(TRIGGERED)));
+ public static final Block SANDSTONE = register(new Block("sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CHISELED_SANDSTONE = register(new Block("chiseled_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CUT_SANDSTONE = register(new Block("cut_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block NOTE_BLOCK = register(new Block("note_block", builder().destroyTime(0.8f)
+ .enumState(NOTEBLOCK_INSTRUMENT)
+ .intState(NOTE)
+ .booleanState(POWERED)));
+ public static final Block WHITE_BED = register(new BedBlock("white_bed", 0, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block ORANGE_BED = register(new BedBlock("orange_bed", 1, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block MAGENTA_BED = register(new BedBlock("magenta_bed", 2, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block LIGHT_BLUE_BED = register(new BedBlock("light_blue_bed", 3, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block YELLOW_BED = register(new BedBlock("yellow_bed", 4, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block LIME_BED = register(new BedBlock("lime_bed", 5, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block PINK_BED = register(new BedBlock("pink_bed", 6, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block GRAY_BED = register(new BedBlock("gray_bed", 7, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block LIGHT_GRAY_BED = register(new BedBlock("light_gray_bed", 8, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block CYAN_BED = register(new BedBlock("cyan_bed", 9, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block PURPLE_BED = register(new BedBlock("purple_bed", 10, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block BLUE_BED = register(new BedBlock("blue_bed", 11, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block BROWN_BED = register(new BedBlock("brown_bed", 12, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block GREEN_BED = register(new BedBlock("green_bed", 13, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block RED_BED = register(new BedBlock("red_bed", 14, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block BLACK_BED = register(new BedBlock("black_bed", 15, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OCCUPIED)
+ .enumState(BED_PART)));
+ public static final Block POWERED_RAIL = register(new Block("powered_rail", builder().destroyTime(0.7f)
+ .booleanState(POWERED)
+ .enumState(RAIL_SHAPE_STRAIGHT)
+ .booleanState(WATERLOGGED)));
+ public static final Block DETECTOR_RAIL = register(new Block("detector_rail", builder().destroyTime(0.7f)
+ .booleanState(POWERED)
+ .enumState(RAIL_SHAPE_STRAIGHT)
+ .booleanState(WATERLOGGED)));
+ public static final Block STICKY_PISTON = register(new PistonBlock("sticky_piston", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK)
+ .booleanState(EXTENDED)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block COBWEB = register(new Block("cobweb", builder().requiresCorrectToolForDrops().destroyTime(4.0f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block SHORT_GRASS = register(new Block("short_grass", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block FERN = register(new Block("fern", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block DEAD_BUSH = register(new Block("dead_bush", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block SEAGRASS = register(new Block("seagrass", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block TALL_SEAGRASS = register(new Block("tall_seagrass", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.SEAGRASS)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block PISTON = register(new PistonBlock("piston", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK)
+ .booleanState(EXTENDED)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block PISTON_HEAD = register(new PistonHeadBlock("piston_head", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(SHORT)
+ .enumState(PISTON_TYPE)));
+ public static final Block WHITE_WOOL = register(new Block("white_wool", builder().destroyTime(0.8f)));
+ public static final Block ORANGE_WOOL = register(new Block("orange_wool", builder().destroyTime(0.8f)));
+ public static final Block MAGENTA_WOOL = register(new Block("magenta_wool", builder().destroyTime(0.8f)));
+ public static final Block LIGHT_BLUE_WOOL = register(new Block("light_blue_wool", builder().destroyTime(0.8f)));
+ public static final Block YELLOW_WOOL = register(new Block("yellow_wool", builder().destroyTime(0.8f)));
+ public static final Block LIME_WOOL = register(new Block("lime_wool", builder().destroyTime(0.8f)));
+ public static final Block PINK_WOOL = register(new Block("pink_wool", builder().destroyTime(0.8f)));
+ public static final Block GRAY_WOOL = register(new Block("gray_wool", builder().destroyTime(0.8f)));
+ public static final Block LIGHT_GRAY_WOOL = register(new Block("light_gray_wool", builder().destroyTime(0.8f)));
+ public static final Block CYAN_WOOL = register(new Block("cyan_wool", builder().destroyTime(0.8f)));
+ public static final Block PURPLE_WOOL = register(new Block("purple_wool", builder().destroyTime(0.8f)));
+ public static final Block BLUE_WOOL = register(new Block("blue_wool", builder().destroyTime(0.8f)));
+ public static final Block BROWN_WOOL = register(new Block("brown_wool", builder().destroyTime(0.8f)));
+ public static final Block GREEN_WOOL = register(new Block("green_wool", builder().destroyTime(0.8f)));
+ public static final Block RED_WOOL = register(new Block("red_wool", builder().destroyTime(0.8f)));
+ public static final Block BLACK_WOOL = register(new Block("black_wool", builder().destroyTime(0.8f)));
+ public static final Block MOVING_PISTON = register(new MovingPistonBlock("moving_piston", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .enumState(PISTON_TYPE)));
+ public static final Block DANDELION = register(new Block("dandelion", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block TORCHFLOWER = register(new Block("torchflower", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POPPY = register(new Block("poppy", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block BLUE_ORCHID = register(new Block("blue_orchid", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block ALLIUM = register(new Block("allium", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block AZURE_BLUET = register(new Block("azure_bluet", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block RED_TULIP = register(new Block("red_tulip", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block ORANGE_TULIP = register(new Block("orange_tulip", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block WHITE_TULIP = register(new Block("white_tulip", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block PINK_TULIP = register(new Block("pink_tulip", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block OXEYE_DAISY = register(new Block("oxeye_daisy", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block CORNFLOWER = register(new Block("cornflower", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block WITHER_ROSE = register(new Block("wither_rose", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block LILY_OF_THE_VALLEY = register(new Block("lily_of_the_valley", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block BROWN_MUSHROOM = register(new Block("brown_mushroom", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block RED_MUSHROOM = register(new Block("red_mushroom", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block GOLD_BLOCK = register(new Block("gold_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block IRON_BLOCK = register(new Block("iron_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block BRICKS = register(new Block("bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block TNT = register(new Block("tnt", builder()
+ .booleanState(UNSTABLE)));
+ public static final Block BOOKSHELF = register(new Block("bookshelf", builder().destroyTime(1.5f)));
+ public static final Block CHISELED_BOOKSHELF = register(new Block("chiseled_bookshelf", builder().setBlockEntity().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_0_OCCUPIED)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_1_OCCUPIED)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_2_OCCUPIED)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_3_OCCUPIED)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_4_OCCUPIED)
+ .booleanState(CHISELED_BOOKSHELF_SLOT_5_OCCUPIED)));
+ public static final Block MOSSY_COBBLESTONE = register(new Block("mossy_cobblestone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block OBSIDIAN = register(new Block("obsidian", builder().requiresCorrectToolForDrops().destroyTime(50.0f)));
+ public static final Block TORCH = register(new Block("torch", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block WALL_TORCH = register(new Block("wall_torch", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block FIRE = register(new Block("fire", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_15)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block SOUL_FIRE = register(new Block("soul_fire", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block SPAWNER = register(new SpawnerBlock("spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHEST = register(new ChestBlock("chest", builder().setBlockEntity().destroyTime(2.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(CHEST_TYPE, ChestType.VALUES)
+ .booleanState(WATERLOGGED)));
+ public static final Block REDSTONE_WIRE = register(new Block("redstone_wire", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(EAST_REDSTONE)
+ .enumState(NORTH_REDSTONE)
+ .intState(POWER)
+ .enumState(SOUTH_REDSTONE)
+ .enumState(WEST_REDSTONE)));
+ public static final Block DIAMOND_ORE = register(new Block("diamond_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_DIAMOND_ORE = register(new Block("deepslate_diamond_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block DIAMOND_BLOCK = register(new Block("diamond_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block CRAFTING_TABLE = register(new Block("crafting_table", builder().destroyTime(2.5f)));
+ public static final Block WHEAT = register(new Block("wheat", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_7)));
+ public static final Block FARMLAND = register(new Block("farmland", builder().destroyTime(0.6f)
+ .intState(MOISTURE)));
+ public static final Block FURNACE = register(new FurnaceBlock("furnace", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)));
+ public static final Block OAK_SIGN = register(new Block("oak_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_SIGN = register(new Block("spruce_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_SIGN = register(new Block("birch_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_SIGN = register(new Block("acacia_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_SIGN = register(new Block("cherry_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_SIGN = register(new Block("jungle_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_SIGN = register(new Block("dark_oak_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_SIGN = register(new Block("mangrove_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_SIGN = register(new Block("bamboo_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block OAK_DOOR = register(new DoorBlock("oak_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block LADDER = register(new Block("ladder", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block RAIL = register(new Block("rail", builder().destroyTime(0.7f)
+ .enumState(RAIL_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COBBLESTONE_STAIRS = register(new Block("cobblestone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block OAK_WALL_SIGN = register(new Block("oak_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_WALL_SIGN = register(new Block("spruce_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_WALL_SIGN = register(new Block("birch_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_WALL_SIGN = register(new Block("acacia_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_WALL_SIGN = register(new Block("cherry_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_WALL_SIGN = register(new Block("jungle_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_WALL_SIGN = register(new Block("dark_oak_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_WALL_SIGN = register(new Block("mangrove_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_WALL_SIGN = register(new Block("bamboo_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block OAK_HANGING_SIGN = register(new Block("oak_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_HANGING_SIGN = register(new Block("spruce_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_HANGING_SIGN = register(new Block("birch_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_HANGING_SIGN = register(new Block("acacia_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_HANGING_SIGN = register(new Block("cherry_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_HANGING_SIGN = register(new Block("jungle_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_HANGING_SIGN = register(new Block("dark_oak_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_HANGING_SIGN = register(new Block("crimson_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_HANGING_SIGN = register(new Block("warped_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_HANGING_SIGN = register(new Block("mangrove_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_HANGING_SIGN = register(new Block("bamboo_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .booleanState(ATTACHED)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block OAK_WALL_HANGING_SIGN = register(new Block("oak_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_WALL_HANGING_SIGN = register(new Block("spruce_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_WALL_HANGING_SIGN = register(new Block("birch_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_WALL_HANGING_SIGN = register(new Block("acacia_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_WALL_HANGING_SIGN = register(new Block("cherry_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_WALL_HANGING_SIGN = register(new Block("jungle_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_WALL_HANGING_SIGN = register(new Block("dark_oak_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_WALL_HANGING_SIGN = register(new Block("mangrove_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_WALL_HANGING_SIGN = register(new Block("crimson_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_WALL_HANGING_SIGN = register(new Block("warped_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_WALL_HANGING_SIGN = register(new Block("bamboo_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block LEVER = register(new Block("lever", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block STONE_PRESSURE_PLATE = register(new Block("stone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block IRON_DOOR = register(new DoorBlock("iron_door", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block OAK_PRESSURE_PLATE = register(new Block("oak_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block SPRUCE_PRESSURE_PLATE = register(new Block("spruce_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block BIRCH_PRESSURE_PLATE = register(new Block("birch_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block JUNGLE_PRESSURE_PLATE = register(new Block("jungle_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block ACACIA_PRESSURE_PLATE = register(new Block("acacia_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block CHERRY_PRESSURE_PLATE = register(new Block("cherry_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block DARK_OAK_PRESSURE_PLATE = register(new Block("dark_oak_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block MANGROVE_PRESSURE_PLATE = register(new Block("mangrove_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block BAMBOO_PRESSURE_PLATE = register(new Block("bamboo_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block REDSTONE_ORE = register(new Block("redstone_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)));
+ public static final Block DEEPSLATE_REDSTONE_ORE = register(new Block("deepslate_redstone_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)
+ .booleanState(LIT)));
+ public static final Block REDSTONE_TORCH = register(new Block("redstone_torch", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(LIT)));
+ public static final Block REDSTONE_WALL_TORCH = register(new Block("redstone_wall_torch", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)));
+ public static final Block STONE_BUTTON = register(new Block("stone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block SNOW = register(new Block("snow", builder().requiresCorrectToolForDrops().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(LAYERS)));
+ public static final Block ICE = register(new Block("ice", builder().destroyTime(0.5f)));
+ public static final Block SNOW_BLOCK = register(new Block("snow_block", builder().requiresCorrectToolForDrops().destroyTime(0.2f)));
+ public static final Block CACTUS = register(new Block("cactus", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_15)));
+ public static final Block CLAY = register(new Block("clay", builder().destroyTime(0.6f)));
+ public static final Block SUGAR_CANE = register(new Block("sugar_cane", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_15)));
+ public static final Block JUKEBOX = register(new Block("jukebox", builder().setBlockEntity().destroyTime(2.0f)
+ .booleanState(HAS_RECORD)));
+ public static final Block OAK_FENCE = register(new Block("oak_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block NETHERRACK = register(new Block("netherrack", builder().requiresCorrectToolForDrops().destroyTime(0.4f)));
+ public static final Block SOUL_SAND = register(new Block("soul_sand", builder().destroyTime(0.5f)));
+ public static final Block SOUL_SOIL = register(new Block("soul_soil", builder().destroyTime(0.5f)));
+ public static final Block BASALT = register(new Block("basalt", builder().requiresCorrectToolForDrops().destroyTime(1.25f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block POLISHED_BASALT = register(new Block("polished_basalt", builder().requiresCorrectToolForDrops().destroyTime(1.25f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block SOUL_TORCH = register(new Block("soul_torch", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block SOUL_WALL_TORCH = register(new Block("soul_wall_torch", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block GLOWSTONE = register(new Block("glowstone", builder().destroyTime(0.3f)));
+ public static final Block NETHER_PORTAL = register(new Block("nether_portal", builder().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(HORIZONTAL_AXIS, Axis.X, Axis.Z)));
+ public static final Block CARVED_PUMPKIN = register(new Block("carved_pumpkin", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block JACK_O_LANTERN = register(new Block("jack_o_lantern", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block CAKE = register(new Block("cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .intState(BITES)));
+ public static final Block REPEATER = register(new Block("repeater", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(DELAY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LOCKED)
+ .booleanState(POWERED)));
+ public static final Block WHITE_STAINED_GLASS = register(new Block("white_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block ORANGE_STAINED_GLASS = register(new Block("orange_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block MAGENTA_STAINED_GLASS = register(new Block("magenta_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block LIGHT_BLUE_STAINED_GLASS = register(new Block("light_blue_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block YELLOW_STAINED_GLASS = register(new Block("yellow_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block LIME_STAINED_GLASS = register(new Block("lime_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block PINK_STAINED_GLASS = register(new Block("pink_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block GRAY_STAINED_GLASS = register(new Block("gray_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block LIGHT_GRAY_STAINED_GLASS = register(new Block("light_gray_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block CYAN_STAINED_GLASS = register(new Block("cyan_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block PURPLE_STAINED_GLASS = register(new Block("purple_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block BLUE_STAINED_GLASS = register(new Block("blue_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block BROWN_STAINED_GLASS = register(new Block("brown_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block GREEN_STAINED_GLASS = register(new Block("green_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block RED_STAINED_GLASS = register(new Block("red_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block BLACK_STAINED_GLASS = register(new Block("black_stained_glass", builder().destroyTime(0.3f)));
+ public static final Block OAK_TRAPDOOR = register(new TrapDoorBlock("oak_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_TRAPDOOR = register(new TrapDoorBlock("spruce_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_TRAPDOOR = register(new TrapDoorBlock("birch_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_TRAPDOOR = register(new TrapDoorBlock("jungle_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_TRAPDOOR = register(new TrapDoorBlock("acacia_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_TRAPDOOR = register(new TrapDoorBlock("cherry_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_TRAPDOOR = register(new TrapDoorBlock("dark_oak_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_TRAPDOOR = register(new TrapDoorBlock("mangrove_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_TRAPDOOR = register(new TrapDoorBlock("bamboo_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block STONE_BRICKS = register(new Block("stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block MOSSY_STONE_BRICKS = register(new Block("mossy_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CRACKED_STONE_BRICKS = register(new Block("cracked_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CHISELED_STONE_BRICKS = register(new Block("chiseled_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block PACKED_MUD = register(new Block("packed_mud", builder().destroyTime(1.0f)));
+ public static final Block MUD_BRICKS = register(new Block("mud_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block INFESTED_STONE = register(new Block("infested_stone", builder().destroyTime(0.75f)));
+ public static final Block INFESTED_COBBLESTONE = register(new Block("infested_cobblestone", builder().destroyTime(1.0f)));
+ public static final Block INFESTED_STONE_BRICKS = register(new Block("infested_stone_bricks", builder().destroyTime(0.75f)));
+ public static final Block INFESTED_MOSSY_STONE_BRICKS = register(new Block("infested_mossy_stone_bricks", builder().destroyTime(0.75f)));
+ public static final Block INFESTED_CRACKED_STONE_BRICKS = register(new Block("infested_cracked_stone_bricks", builder().destroyTime(0.75f)));
+ public static final Block INFESTED_CHISELED_STONE_BRICKS = register(new Block("infested_chiseled_stone_bricks", builder().destroyTime(0.75f)));
+ public static final Block BROWN_MUSHROOM_BLOCK = register(new Block("brown_mushroom_block", builder().destroyTime(0.2f)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block RED_MUSHROOM_BLOCK = register(new Block("red_mushroom_block", builder().destroyTime(0.2f)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block MUSHROOM_STEM = register(new Block("mushroom_stem", builder().destroyTime(0.2f)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block IRON_BARS = register(new Block("iron_bars", builder().requiresCorrectToolForDrops().destroyTime(5.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block CHAIN = register(new Block("chain", builder().requiresCorrectToolForDrops().destroyTime(5.0f)
+ .enumState(AXIS, Axis.VALUES)
+ .booleanState(WATERLOGGED)));
+ public static final Block GLASS_PANE = register(new Block("glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block PUMPKIN = register(new Block("pumpkin", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block MELON = register(new Block("melon", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block ATTACHED_PUMPKIN_STEM = register(new Block("attached_pumpkin_stem", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.PUMPKIN_SEEDS)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block ATTACHED_MELON_STEM = register(new Block("attached_melon_stem", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.MELON_SEEDS)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block PUMPKIN_STEM = register(new Block("pumpkin_stem", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_7)));
+ public static final Block MELON_STEM = register(new Block("melon_stem", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_7)));
+ public static final Block VINE = register(new Block("vine", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block GLOW_LICHEN = register(new Block("glow_lichen", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block OAK_FENCE_GATE = register(new Block("oak_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block BRICK_STAIRS = register(new Block("brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block STONE_BRICK_STAIRS = register(new Block("stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MUD_BRICK_STAIRS = register(new Block("mud_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MYCELIUM = register(new Block("mycelium", builder().destroyTime(0.6f)
+ .booleanState(SNOWY)));
+ public static final Block LILY_PAD = register(new Block("lily_pad", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block NETHER_BRICKS = register(new Block("nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block NETHER_BRICK_FENCE = register(new Block("nether_brick_fence", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block NETHER_BRICK_STAIRS = register(new Block("nether_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block NETHER_WART = register(new Block("nether_wart", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_3)));
+ public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block BREWING_STAND = register(new Block("brewing_stand", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(0.5f)
+ .booleanState(HAS_BOTTLE_0)
+ .booleanState(HAS_BOTTLE_1)
+ .booleanState(HAS_BOTTLE_2)));
+ public static final Block CAULDRON = register(new CauldronBlock("cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block WATER_CAULDRON = register(new CauldronBlock("water_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .intState(LEVEL_CAULDRON)));
+ public static final Block LAVA_CAULDRON = register(new CauldronBlock("lava_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block POWDER_SNOW_CAULDRON = register(new CauldronBlock("powder_snow_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .intState(LEVEL_CAULDRON)));
+ public static final Block END_PORTAL = register(new Block("end_portal", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK)));
+ public static final Block END_PORTAL_FRAME = register(new Block("end_portal_frame", builder().destroyTime(-1.0f)
+ .booleanState(EYE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block END_STONE = register(new Block("end_stone", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DRAGON_EGG = register(new Block("dragon_egg", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block REDSTONE_LAMP = register(new Block("redstone_lamp", builder().destroyTime(0.3f)
+ .booleanState(LIT)));
+ public static final Block COCOA = register(new Block("cocoa", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_2)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block SANDSTONE_STAIRS = register(new Block("sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block EMERALD_ORE = register(new Block("emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_EMERALD_ORE = register(new Block("deepslate_emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block ENDER_CHEST = register(new Block("ender_chest", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(22.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block TRIPWIRE_HOOK = register(new Block("tripwire_hook", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(ATTACHED)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block TRIPWIRE = register(new Block("tripwire", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(ATTACHED)
+ .booleanState(DISARMED)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(POWERED)
+ .booleanState(SOUTH)
+ .booleanState(WEST)));
+ public static final Block EMERALD_BLOCK = register(new Block("emerald_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block SPRUCE_STAIRS = register(new Block("spruce_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_STAIRS = register(new Block("birch_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_STAIRS = register(new Block("jungle_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COMMAND_BLOCK = register(new Block("command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f)
+ .booleanState(CONDITIONAL)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block BEACON = register(new Block("beacon", builder().setBlockEntity().destroyTime(3.0f)));
+ public static final Block COBBLESTONE_WALL = register(new Block("cobblestone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block MOSSY_COBBLESTONE_WALL = register(new Block("mossy_cobblestone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block FLOWER_POT = register(new FlowerPotBlock("flower_pot", AIR, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_TORCHFLOWER = register(new FlowerPotBlock("potted_torchflower", TORCHFLOWER, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_OAK_SAPLING = register(new FlowerPotBlock("potted_oak_sapling", OAK_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_SPRUCE_SAPLING = register(new FlowerPotBlock("potted_spruce_sapling", SPRUCE_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_BIRCH_SAPLING = register(new FlowerPotBlock("potted_birch_sapling", BIRCH_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_JUNGLE_SAPLING = register(new FlowerPotBlock("potted_jungle_sapling", JUNGLE_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_ACACIA_SAPLING = register(new FlowerPotBlock("potted_acacia_sapling", ACACIA_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_CHERRY_SAPLING = register(new FlowerPotBlock("potted_cherry_sapling", CHERRY_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_DARK_OAK_SAPLING = register(new FlowerPotBlock("potted_dark_oak_sapling", DARK_OAK_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_MANGROVE_PROPAGULE = register(new FlowerPotBlock("potted_mangrove_propagule", MANGROVE_PROPAGULE, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_FERN = register(new FlowerPotBlock("potted_fern", FERN, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_DANDELION = register(new FlowerPotBlock("potted_dandelion", DANDELION, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_POPPY = register(new FlowerPotBlock("potted_poppy", POPPY, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_BLUE_ORCHID = register(new FlowerPotBlock("potted_blue_orchid", BLUE_ORCHID, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_ALLIUM = register(new FlowerPotBlock("potted_allium", ALLIUM, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_AZURE_BLUET = register(new FlowerPotBlock("potted_azure_bluet", AZURE_BLUET, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_RED_TULIP = register(new FlowerPotBlock("potted_red_tulip", RED_TULIP, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_ORANGE_TULIP = register(new FlowerPotBlock("potted_orange_tulip", ORANGE_TULIP, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_WHITE_TULIP = register(new FlowerPotBlock("potted_white_tulip", WHITE_TULIP, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_PINK_TULIP = register(new FlowerPotBlock("potted_pink_tulip", PINK_TULIP, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_OXEYE_DAISY = register(new FlowerPotBlock("potted_oxeye_daisy", OXEYE_DAISY, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_CORNFLOWER = register(new FlowerPotBlock("potted_cornflower", CORNFLOWER, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_LILY_OF_THE_VALLEY = register(new FlowerPotBlock("potted_lily_of_the_valley", LILY_OF_THE_VALLEY, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_WITHER_ROSE = register(new FlowerPotBlock("potted_wither_rose", WITHER_ROSE, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_RED_MUSHROOM = register(new FlowerPotBlock("potted_red_mushroom", RED_MUSHROOM, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_BROWN_MUSHROOM = register(new FlowerPotBlock("potted_brown_mushroom", BROWN_MUSHROOM, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_DEAD_BUSH = register(new FlowerPotBlock("potted_dead_bush", DEAD_BUSH, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_CACTUS = register(new FlowerPotBlock("potted_cactus", CACTUS, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block CARROTS = register(new Block("carrots", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_7)));
+ public static final Block POTATOES = register(new Block("potatoes", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_7)));
+ public static final Block OAK_BUTTON = register(new Block("oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block SPRUCE_BUTTON = register(new Block("spruce_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block BIRCH_BUTTON = register(new Block("birch_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block JUNGLE_BUTTON = register(new Block("jungle_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block ACACIA_BUTTON = register(new Block("acacia_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block CHERRY_BUTTON = register(new Block("cherry_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block DARK_OAK_BUTTON = register(new Block("dark_oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block MANGROVE_BUTTON = register(new Block("mangrove_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block BAMBOO_BUTTON = register(new Block("bamboo_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block SKELETON_SKULL = register(new SkullBlock("skeleton_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block SKELETON_WALL_SKULL = register(new WallSkullBlock("skeleton_wall_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block WITHER_SKELETON_SKULL = register(new SkullBlock("wither_skeleton_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block WITHER_SKELETON_WALL_SKULL = register(new WallSkullBlock("wither_skeleton_wall_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block ZOMBIE_HEAD = register(new SkullBlock("zombie_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block ZOMBIE_WALL_HEAD = register(new WallSkullBlock("zombie_wall_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block PLAYER_HEAD = register(new SkullBlock("player_head", SkullBlock.Type.PLAYER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block PLAYER_WALL_HEAD = register(new WallSkullBlock("player_wall_head", SkullBlock.Type.PLAYER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block CREEPER_HEAD = register(new SkullBlock("creeper_head", SkullBlock.Type.CREEPER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block CREEPER_WALL_HEAD = register(new WallSkullBlock("creeper_wall_head", SkullBlock.Type.CREEPER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block DRAGON_HEAD = register(new SkullBlock("dragon_head", SkullBlock.Type.DRAGON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block DRAGON_WALL_HEAD = register(new WallSkullBlock("dragon_wall_head", SkullBlock.Type.DRAGON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block PIGLIN_HEAD = register(new SkullBlock("piglin_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)
+ .intState(ROTATION_16)));
+ public static final Block PIGLIN_WALL_HEAD = register(new WallSkullBlock("piglin_wall_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block ANVIL = register(new Block("anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block CHIPPED_ANVIL = register(new Block("chipped_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block DAMAGED_ANVIL = register(new Block("damaged_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block TRAPPED_CHEST = register(new ChestBlock("trapped_chest", builder().setBlockEntity().destroyTime(2.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(CHEST_TYPE, ChestType.VALUES)
+ .booleanState(WATERLOGGED)));
+ public static final Block LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Block("light_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .intState(POWER)));
+ public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .intState(POWER)));
+ public static final Block COMPARATOR = register(new Block("comparator", builder().setBlockEntity().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(MODE_COMPARATOR)
+ .booleanState(POWERED)));
+ public static final Block DAYLIGHT_DETECTOR = register(new Block("daylight_detector", builder().setBlockEntity().destroyTime(0.2f)
+ .booleanState(INVERTED)
+ .intState(POWER)));
+ public static final Block REDSTONE_BLOCK = register(new Block("redstone_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block NETHER_QUARTZ_ORE = register(new Block("nether_quartz_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block HOPPER = register(new Block("hopper", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(ENABLED)
+ .enumState(FACING_HOPPER, Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block QUARTZ_BLOCK = register(new Block("quartz_block", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CHISELED_QUARTZ_BLOCK = register(new Block("chiseled_quartz_block", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block QUARTZ_PILLAR = register(new Block("quartz_pillar", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block QUARTZ_STAIRS = register(new Block("quartz_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACTIVATOR_RAIL = register(new Block("activator_rail", builder().destroyTime(0.7f)
+ .booleanState(POWERED)
+ .enumState(RAIL_SHAPE_STRAIGHT)
+ .booleanState(WATERLOGGED)));
+ public static final Block DROPPER = register(new Block("dropper", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(TRIGGERED)));
+ public static final Block WHITE_TERRACOTTA = register(new Block("white_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block ORANGE_TERRACOTTA = register(new Block("orange_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block MAGENTA_TERRACOTTA = register(new Block("magenta_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block LIGHT_BLUE_TERRACOTTA = register(new Block("light_blue_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block YELLOW_TERRACOTTA = register(new Block("yellow_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block LIME_TERRACOTTA = register(new Block("lime_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block PINK_TERRACOTTA = register(new Block("pink_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block GRAY_TERRACOTTA = register(new Block("gray_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block LIGHT_GRAY_TERRACOTTA = register(new Block("light_gray_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block CYAN_TERRACOTTA = register(new Block("cyan_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block PURPLE_TERRACOTTA = register(new Block("purple_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block BLUE_TERRACOTTA = register(new Block("blue_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block BROWN_TERRACOTTA = register(new Block("brown_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block GREEN_TERRACOTTA = register(new Block("green_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block RED_TERRACOTTA = register(new Block("red_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block BLACK_TERRACOTTA = register(new Block("black_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block WHITE_STAINED_GLASS_PANE = register(new Block("white_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block ORANGE_STAINED_GLASS_PANE = register(new Block("orange_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block MAGENTA_STAINED_GLASS_PANE = register(new Block("magenta_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block LIGHT_BLUE_STAINED_GLASS_PANE = register(new Block("light_blue_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block YELLOW_STAINED_GLASS_PANE = register(new Block("yellow_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block LIME_STAINED_GLASS_PANE = register(new Block("lime_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block PINK_STAINED_GLASS_PANE = register(new Block("pink_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block GRAY_STAINED_GLASS_PANE = register(new Block("gray_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block LIGHT_GRAY_STAINED_GLASS_PANE = register(new Block("light_gray_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block CYAN_STAINED_GLASS_PANE = register(new Block("cyan_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block PURPLE_STAINED_GLASS_PANE = register(new Block("purple_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block BLUE_STAINED_GLASS_PANE = register(new Block("blue_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block BROWN_STAINED_GLASS_PANE = register(new Block("brown_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block GREEN_STAINED_GLASS_PANE = register(new Block("green_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block RED_STAINED_GLASS_PANE = register(new Block("red_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block BLACK_STAINED_GLASS_PANE = register(new Block("black_stained_glass_pane", builder().destroyTime(0.3f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block ACACIA_STAIRS = register(new Block("acacia_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_STAIRS = register(new Block("cherry_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_STAIRS = register(new Block("dark_oak_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_STAIRS = register(new Block("mangrove_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_STAIRS = register(new Block("bamboo_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_MOSAIC_STAIRS = register(new Block("bamboo_mosaic_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SLIME_BLOCK = register(new Block("slime_block", builder()));
+ public static final Block BARRIER = register(new Block("barrier", builder().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK)
+ .booleanState(WATERLOGGED)));
+ public static final Block LIGHT = register(new Block("light", builder().destroyTime(-1.0f)
+ .intState(LEVEL)
+ .booleanState(WATERLOGGED)));
+ public static final Block IRON_TRAPDOOR = register(new TrapDoorBlock("iron_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(5.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block PRISMARINE = register(new Block("prismarine", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block PRISMARINE_BRICKS = register(new Block("prismarine_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DARK_PRISMARINE = register(new Block("dark_prismarine", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block PRISMARINE_STAIRS = register(new Block("prismarine_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block PRISMARINE_BRICK_STAIRS = register(new Block("prismarine_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_PRISMARINE_STAIRS = register(new Block("dark_prismarine_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block PRISMARINE_SLAB = register(new Block("prismarine_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block PRISMARINE_BRICK_SLAB = register(new Block("prismarine_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_PRISMARINE_SLAB = register(new Block("dark_prismarine_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SEA_LANTERN = register(new Block("sea_lantern", builder().destroyTime(0.3f)));
+ public static final Block HAY_BLOCK = register(new Block("hay_block", builder().destroyTime(0.5f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block WHITE_CARPET = register(new Block("white_carpet", builder().destroyTime(0.1f)));
+ public static final Block ORANGE_CARPET = register(new Block("orange_carpet", builder().destroyTime(0.1f)));
+ public static final Block MAGENTA_CARPET = register(new Block("magenta_carpet", builder().destroyTime(0.1f)));
+ public static final Block LIGHT_BLUE_CARPET = register(new Block("light_blue_carpet", builder().destroyTime(0.1f)));
+ public static final Block YELLOW_CARPET = register(new Block("yellow_carpet", builder().destroyTime(0.1f)));
+ public static final Block LIME_CARPET = register(new Block("lime_carpet", builder().destroyTime(0.1f)));
+ public static final Block PINK_CARPET = register(new Block("pink_carpet", builder().destroyTime(0.1f)));
+ public static final Block GRAY_CARPET = register(new Block("gray_carpet", builder().destroyTime(0.1f)));
+ public static final Block LIGHT_GRAY_CARPET = register(new Block("light_gray_carpet", builder().destroyTime(0.1f)));
+ public static final Block CYAN_CARPET = register(new Block("cyan_carpet", builder().destroyTime(0.1f)));
+ public static final Block PURPLE_CARPET = register(new Block("purple_carpet", builder().destroyTime(0.1f)));
+ public static final Block BLUE_CARPET = register(new Block("blue_carpet", builder().destroyTime(0.1f)));
+ public static final Block BROWN_CARPET = register(new Block("brown_carpet", builder().destroyTime(0.1f)));
+ public static final Block GREEN_CARPET = register(new Block("green_carpet", builder().destroyTime(0.1f)));
+ public static final Block RED_CARPET = register(new Block("red_carpet", builder().destroyTime(0.1f)));
+ public static final Block BLACK_CARPET = register(new Block("black_carpet", builder().destroyTime(0.1f)));
+ public static final Block TERRACOTTA = register(new Block("terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block COAL_BLOCK = register(new Block("coal_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block PACKED_ICE = register(new Block("packed_ice", builder().destroyTime(0.5f)));
+ public static final Block SUNFLOWER = register(new Block("sunflower", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block LILAC = register(new Block("lilac", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block ROSE_BUSH = register(new Block("rose_bush", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block PEONY = register(new Block("peony", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block TALL_GRASS = register(new Block("tall_grass", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block LARGE_FERN = register(new Block("large_fern", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block WHITE_BANNER = register(new BannerBlock("white_banner", 0, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block ORANGE_BANNER = register(new BannerBlock("orange_banner", 1, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block MAGENTA_BANNER = register(new BannerBlock("magenta_banner", 2, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block LIGHT_BLUE_BANNER = register(new BannerBlock("light_blue_banner", 3, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block YELLOW_BANNER = register(new BannerBlock("yellow_banner", 4, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block LIME_BANNER = register(new BannerBlock("lime_banner", 5, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block PINK_BANNER = register(new BannerBlock("pink_banner", 6, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block GRAY_BANNER = register(new BannerBlock("gray_banner", 7, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block LIGHT_GRAY_BANNER = register(new BannerBlock("light_gray_banner", 8, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block CYAN_BANNER = register(new BannerBlock("cyan_banner", 9, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block PURPLE_BANNER = register(new BannerBlock("purple_banner", 10, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block BLUE_BANNER = register(new BannerBlock("blue_banner", 11, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block BROWN_BANNER = register(new BannerBlock("brown_banner", 12, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block GREEN_BANNER = register(new BannerBlock("green_banner", 13, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block RED_BANNER = register(new BannerBlock("red_banner", 14, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block BLACK_BANNER = register(new BannerBlock("black_banner", 15, builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)));
+ public static final Block WHITE_WALL_BANNER = register(new BannerBlock("white_wall_banner", 0, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block ORANGE_WALL_BANNER = register(new BannerBlock("orange_wall_banner", 1, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block MAGENTA_WALL_BANNER = register(new BannerBlock("magenta_wall_banner", 2, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIGHT_BLUE_WALL_BANNER = register(new BannerBlock("light_blue_wall_banner", 3, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block YELLOW_WALL_BANNER = register(new BannerBlock("yellow_wall_banner", 4, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIME_WALL_BANNER = register(new BannerBlock("lime_wall_banner", 5, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block PINK_WALL_BANNER = register(new BannerBlock("pink_wall_banner", 6, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block GRAY_WALL_BANNER = register(new BannerBlock("gray_wall_banner", 7, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIGHT_GRAY_WALL_BANNER = register(new BannerBlock("light_gray_wall_banner", 8, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block CYAN_WALL_BANNER = register(new BannerBlock("cyan_wall_banner", 9, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block PURPLE_WALL_BANNER = register(new BannerBlock("purple_wall_banner", 10, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BLUE_WALL_BANNER = register(new BannerBlock("blue_wall_banner", 11, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BROWN_WALL_BANNER = register(new BannerBlock("brown_wall_banner", 12, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block GREEN_WALL_BANNER = register(new BannerBlock("green_wall_banner", 13, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block RED_WALL_BANNER = register(new BannerBlock("red_wall_banner", 14, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BLACK_WALL_BANNER = register(new BannerBlock("black_wall_banner", 15, builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block RED_SANDSTONE = register(new Block("red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CHISELED_RED_SANDSTONE = register(new Block("chiseled_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CUT_RED_SANDSTONE = register(new Block("cut_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block RED_SANDSTONE_STAIRS = register(new Block("red_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block OAK_SLAB = register(new Block("oak_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SPRUCE_SLAB = register(new Block("spruce_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIRCH_SLAB = register(new Block("birch_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block JUNGLE_SLAB = register(new Block("jungle_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block ACACIA_SLAB = register(new Block("acacia_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CHERRY_SLAB = register(new Block("cherry_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DARK_OAK_SLAB = register(new Block("dark_oak_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MANGROVE_SLAB = register(new Block("mangrove_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_SLAB = register(new Block("bamboo_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_MOSAIC_SLAB = register(new Block("bamboo_mosaic_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block STONE_SLAB = register(new Block("stone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_STONE_SLAB = register(new Block("smooth_stone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SANDSTONE_SLAB = register(new Block("sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CUT_SANDSTONE_SLAB = register(new Block("cut_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block PETRIFIED_OAK_SLAB = register(new Block("petrified_oak_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COBBLESTONE_SLAB = register(new Block("cobblestone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BRICK_SLAB = register(new Block("brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block STONE_BRICK_SLAB = register(new Block("stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MUD_BRICK_SLAB = register(new Block("mud_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block NETHER_BRICK_SLAB = register(new Block("nether_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block QUARTZ_SLAB = register(new Block("quartz_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block RED_SANDSTONE_SLAB = register(new Block("red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CUT_RED_SANDSTONE_SLAB = register(new Block("cut_red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block PURPUR_SLAB = register(new Block("purpur_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_STONE = register(new Block("smooth_stone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block SMOOTH_SANDSTONE = register(new Block("smooth_sandstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block SMOOTH_QUARTZ = register(new Block("smooth_quartz", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block SMOOTH_RED_SANDSTONE = register(new Block("smooth_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block SPRUCE_FENCE_GATE = register(new Block("spruce_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block BIRCH_FENCE_GATE = register(new Block("birch_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block JUNGLE_FENCE_GATE = register(new Block("jungle_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block ACACIA_FENCE_GATE = register(new Block("acacia_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block CHERRY_FENCE_GATE = register(new Block("cherry_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block DARK_OAK_FENCE_GATE = register(new Block("dark_oak_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block MANGROVE_FENCE_GATE = register(new Block("mangrove_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block BAMBOO_FENCE_GATE = register(new Block("bamboo_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block SPRUCE_FENCE = register(new Block("spruce_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block BIRCH_FENCE = register(new Block("birch_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block JUNGLE_FENCE = register(new Block("jungle_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block ACACIA_FENCE = register(new Block("acacia_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block CHERRY_FENCE = register(new Block("cherry_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block DARK_OAK_FENCE = register(new Block("dark_oak_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block MANGROVE_FENCE = register(new Block("mangrove_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block BAMBOO_FENCE = register(new Block("bamboo_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block SPRUCE_DOOR = register(new DoorBlock("spruce_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block BIRCH_DOOR = register(new DoorBlock("birch_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block JUNGLE_DOOR = register(new DoorBlock("jungle_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block ACACIA_DOOR = register(new DoorBlock("acacia_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block CHERRY_DOOR = register(new DoorBlock("cherry_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block DARK_OAK_DOOR = register(new DoorBlock("dark_oak_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block MANGROVE_DOOR = register(new DoorBlock("mangrove_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block BAMBOO_DOOR = register(new DoorBlock("bamboo_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block END_ROD = register(new Block("end_rod", builder()
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block CHORUS_PLANT = register(new Block("chorus_plant", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WEST)));
+ public static final Block CHORUS_FLOWER = register(new Block("chorus_flower", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_5)));
+ public static final Block PURPUR_BLOCK = register(new Block("purpur_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block PURPUR_PILLAR = register(new Block("purpur_pillar", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block PURPUR_STAIRS = register(new Block("purpur_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block END_STONE_BRICKS = register(new Block("end_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block TORCHFLOWER_CROP = register(new Block("torchflower_crop", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_1)));
+ public static final Block PITCHER_CROP = register(new Block("pitcher_crop", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_4)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block PITCHER_PLANT = register(new Block("pitcher_plant", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(DOUBLE_BLOCK_HALF)));
+ public static final Block BEETROOTS = register(new Block("beetroots", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_3)));
+ public static final Block DIRT_PATH = register(new Block("dirt_path", builder().destroyTime(0.65f)));
+ public static final Block END_GATEWAY = register(new Block("end_gateway", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK)));
+ public static final Block REPEATING_COMMAND_BLOCK = register(new Block("repeating_command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f)
+ .booleanState(CONDITIONAL)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block CHAIN_COMMAND_BLOCK = register(new Block("chain_command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f)
+ .booleanState(CONDITIONAL)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block FROSTED_ICE = register(new Block("frosted_ice", builder().destroyTime(0.5f)
+ .intState(AGE_3)));
+ public static final Block MAGMA_BLOCK = register(new Block("magma_block", builder().requiresCorrectToolForDrops().destroyTime(0.5f)));
+ public static final Block NETHER_WART_BLOCK = register(new Block("nether_wart_block", builder().destroyTime(1.0f)));
+ public static final Block RED_NETHER_BRICKS = register(new Block("red_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block BONE_BLOCK = register(new Block("bone_block", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRUCTURE_VOID = register(new Block("structure_void", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block OBSERVER = register(new Block("observer", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(POWERED)));
+ public static final Block SHULKER_BOX = register(new Block("shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block WHITE_SHULKER_BOX = register(new Block("white_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block ORANGE_SHULKER_BOX = register(new Block("orange_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block MAGENTA_SHULKER_BOX = register(new Block("magenta_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block LIGHT_BLUE_SHULKER_BOX = register(new Block("light_blue_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block YELLOW_SHULKER_BOX = register(new Block("yellow_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block LIME_SHULKER_BOX = register(new Block("lime_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block PINK_SHULKER_BOX = register(new Block("pink_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block GRAY_SHULKER_BOX = register(new Block("gray_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block LIGHT_GRAY_SHULKER_BOX = register(new Block("light_gray_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block CYAN_SHULKER_BOX = register(new Block("cyan_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block PURPLE_SHULKER_BOX = register(new Block("purple_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block BLUE_SHULKER_BOX = register(new Block("blue_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block BROWN_SHULKER_BOX = register(new Block("brown_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block GREEN_SHULKER_BOX = register(new Block("green_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block RED_SHULKER_BOX = register(new Block("red_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block BLACK_SHULKER_BOX = register(new Block("black_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)));
+ public static final Block WHITE_GLAZED_TERRACOTTA = register(new Block("white_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block ORANGE_GLAZED_TERRACOTTA = register(new Block("orange_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block MAGENTA_GLAZED_TERRACOTTA = register(new Block("magenta_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIGHT_BLUE_GLAZED_TERRACOTTA = register(new Block("light_blue_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block YELLOW_GLAZED_TERRACOTTA = register(new Block("yellow_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIME_GLAZED_TERRACOTTA = register(new Block("lime_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block PINK_GLAZED_TERRACOTTA = register(new Block("pink_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block GRAY_GLAZED_TERRACOTTA = register(new Block("gray_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LIGHT_GRAY_GLAZED_TERRACOTTA = register(new Block("light_gray_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block CYAN_GLAZED_TERRACOTTA = register(new Block("cyan_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block PURPLE_GLAZED_TERRACOTTA = register(new Block("purple_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BLUE_GLAZED_TERRACOTTA = register(new Block("blue_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BROWN_GLAZED_TERRACOTTA = register(new Block("brown_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block GREEN_GLAZED_TERRACOTTA = register(new Block("green_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block RED_GLAZED_TERRACOTTA = register(new Block("red_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BLACK_GLAZED_TERRACOTTA = register(new Block("black_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block WHITE_CONCRETE = register(new Block("white_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block ORANGE_CONCRETE = register(new Block("orange_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block MAGENTA_CONCRETE = register(new Block("magenta_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block LIGHT_BLUE_CONCRETE = register(new Block("light_blue_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block YELLOW_CONCRETE = register(new Block("yellow_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block LIME_CONCRETE = register(new Block("lime_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block PINK_CONCRETE = register(new Block("pink_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block GRAY_CONCRETE = register(new Block("gray_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block LIGHT_GRAY_CONCRETE = register(new Block("light_gray_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block CYAN_CONCRETE = register(new Block("cyan_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block PURPLE_CONCRETE = register(new Block("purple_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block BLUE_CONCRETE = register(new Block("blue_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block BROWN_CONCRETE = register(new Block("brown_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block GREEN_CONCRETE = register(new Block("green_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block RED_CONCRETE = register(new Block("red_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block BLACK_CONCRETE = register(new Block("black_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f)));
+ public static final Block WHITE_CONCRETE_POWDER = register(new Block("white_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block ORANGE_CONCRETE_POWDER = register(new Block("orange_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block MAGENTA_CONCRETE_POWDER = register(new Block("magenta_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block LIGHT_BLUE_CONCRETE_POWDER = register(new Block("light_blue_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block YELLOW_CONCRETE_POWDER = register(new Block("yellow_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block LIME_CONCRETE_POWDER = register(new Block("lime_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block PINK_CONCRETE_POWDER = register(new Block("pink_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block GRAY_CONCRETE_POWDER = register(new Block("gray_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block LIGHT_GRAY_CONCRETE_POWDER = register(new Block("light_gray_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block CYAN_CONCRETE_POWDER = register(new Block("cyan_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block PURPLE_CONCRETE_POWDER = register(new Block("purple_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block BLUE_CONCRETE_POWDER = register(new Block("blue_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block BROWN_CONCRETE_POWDER = register(new Block("brown_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block GREEN_CONCRETE_POWDER = register(new Block("green_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block RED_CONCRETE_POWDER = register(new Block("red_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block BLACK_CONCRETE_POWDER = register(new Block("black_concrete_powder", builder().destroyTime(0.5f)));
+ public static final Block KELP = register(new Block("kelp", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_25)));
+ public static final Block KELP_PLANT = register(new Block("kelp_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.KELP)));
+ public static final Block DRIED_KELP_BLOCK = register(new Block("dried_kelp_block", builder().destroyTime(0.5f)));
+ public static final Block TURTLE_EGG = register(new Block("turtle_egg", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .intState(EGGS)
+ .intState(HATCH)));
+ public static final Block SNIFFER_EGG = register(new Block("sniffer_egg", builder().destroyTime(0.5f)
+ .intState(HATCH)));
+ public static final Block DEAD_TUBE_CORAL_BLOCK = register(new Block("dead_tube_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DEAD_BRAIN_CORAL_BLOCK = register(new Block("dead_brain_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DEAD_BUBBLE_CORAL_BLOCK = register(new Block("dead_bubble_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DEAD_FIRE_CORAL_BLOCK = register(new Block("dead_fire_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DEAD_HORN_CORAL_BLOCK = register(new Block("dead_horn_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block TUBE_CORAL_BLOCK = register(new Block("tube_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block BRAIN_CORAL_BLOCK = register(new Block("brain_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block BUBBLE_CORAL_BLOCK = register(new Block("bubble_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block FIRE_CORAL_BLOCK = register(new Block("fire_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block HORN_CORAL_BLOCK = register(new Block("horn_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block DEAD_TUBE_CORAL = register(new Block("dead_tube_coral", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BRAIN_CORAL = register(new Block("dead_brain_coral", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BUBBLE_CORAL = register(new Block("dead_bubble_coral", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_FIRE_CORAL = register(new Block("dead_fire_coral", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_HORN_CORAL = register(new Block("dead_horn_coral", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block TUBE_CORAL = register(new Block("tube_coral", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block BRAIN_CORAL = register(new Block("brain_coral", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block BUBBLE_CORAL = register(new Block("bubble_coral", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block FIRE_CORAL = register(new Block("fire_coral", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block HORN_CORAL = register(new Block("horn_coral", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_TUBE_CORAL_FAN = register(new Block("dead_tube_coral_fan", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BRAIN_CORAL_FAN = register(new Block("dead_brain_coral_fan", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BUBBLE_CORAL_FAN = register(new Block("dead_bubble_coral_fan", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_FIRE_CORAL_FAN = register(new Block("dead_fire_coral_fan", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_HORN_CORAL_FAN = register(new Block("dead_horn_coral_fan", builder().requiresCorrectToolForDrops()
+ .booleanState(WATERLOGGED)));
+ public static final Block TUBE_CORAL_FAN = register(new Block("tube_coral_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block BRAIN_CORAL_FAN = register(new Block("brain_coral_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block BUBBLE_CORAL_FAN = register(new Block("bubble_coral_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block FIRE_CORAL_FAN = register(new Block("fire_coral_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block HORN_CORAL_FAN = register(new Block("horn_coral_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_TUBE_CORAL_WALL_FAN = register(new Block("dead_tube_coral_wall_fan", builder().requiresCorrectToolForDrops()
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BRAIN_CORAL_WALL_FAN = register(new Block("dead_brain_coral_wall_fan", builder().requiresCorrectToolForDrops()
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_BUBBLE_CORAL_WALL_FAN = register(new Block("dead_bubble_coral_wall_fan", builder().requiresCorrectToolForDrops()
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_FIRE_CORAL_WALL_FAN = register(new Block("dead_fire_coral_wall_fan", builder().requiresCorrectToolForDrops()
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEAD_HORN_CORAL_WALL_FAN = register(new Block("dead_horn_coral_wall_fan", builder().requiresCorrectToolForDrops()
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUBE_CORAL_WALL_FAN = register(new Block("tube_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BRAIN_CORAL_WALL_FAN = register(new Block("brain_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block BUBBLE_CORAL_WALL_FAN = register(new Block("bubble_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block FIRE_CORAL_WALL_FAN = register(new Block("fire_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block HORN_CORAL_WALL_FAN = register(new Block("horn_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block SEA_PICKLE = register(new Block("sea_pickle", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(PICKLES)
+ .booleanState(WATERLOGGED)));
+ public static final Block BLUE_ICE = register(new Block("blue_ice", builder().destroyTime(2.8f)));
+ public static final Block CONDUIT = register(new Block("conduit", builder().setBlockEntity().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.BAMBOO)));
+ public static final Block BAMBOO = register(new Block("bamboo", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_1)
+ .enumState(BAMBOO_LEAVES)
+ .intState(STAGE)));
+ public static final Block POTTED_BAMBOO = register(new FlowerPotBlock("potted_bamboo", BAMBOO, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block VOID_AIR = register(new Block("void_air", builder()));
+ public static final Block CAVE_AIR = register(new Block("cave_air", builder()));
+ public static final Block BUBBLE_COLUMN = register(new Block("bubble_column", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(DRAG)));
+ public static final Block POLISHED_GRANITE_STAIRS = register(new Block("polished_granite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_RED_SANDSTONE_STAIRS = register(new Block("smooth_red_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MOSSY_STONE_BRICK_STAIRS = register(new Block("mossy_stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_DIORITE_STAIRS = register(new Block("polished_diorite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MOSSY_COBBLESTONE_STAIRS = register(new Block("mossy_cobblestone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block END_STONE_BRICK_STAIRS = register(new Block("end_stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block STONE_STAIRS = register(new Block("stone_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_SANDSTONE_STAIRS = register(new Block("smooth_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_QUARTZ_STAIRS = register(new Block("smooth_quartz_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block GRANITE_STAIRS = register(new Block("granite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block ANDESITE_STAIRS = register(new Block("andesite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block RED_NETHER_BRICK_STAIRS = register(new Block("red_nether_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_ANDESITE_STAIRS = register(new Block("polished_andesite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DIORITE_STAIRS = register(new Block("diorite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_GRANITE_SLAB = register(new Block("polished_granite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_RED_SANDSTONE_SLAB = register(new Block("smooth_red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MOSSY_STONE_BRICK_SLAB = register(new Block("mossy_stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_DIORITE_SLAB = register(new Block("polished_diorite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block MOSSY_COBBLESTONE_SLAB = register(new Block("mossy_cobblestone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block END_STONE_BRICK_SLAB = register(new Block("end_stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_SANDSTONE_SLAB = register(new Block("smooth_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMOOTH_QUARTZ_SLAB = register(new Block("smooth_quartz_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block GRANITE_SLAB = register(new Block("granite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block ANDESITE_SLAB = register(new Block("andesite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block RED_NETHER_BRICK_SLAB = register(new Block("red_nether_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_ANDESITE_SLAB = register(new Block("polished_andesite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DIORITE_SLAB = register(new Block("diorite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BRICK_WALL = register(new Block("brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block PRISMARINE_WALL = register(new Block("prismarine_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block RED_SANDSTONE_WALL = register(new Block("red_sandstone_wall", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block MOSSY_STONE_BRICK_WALL = register(new Block("mossy_stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block GRANITE_WALL = register(new Block("granite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block STONE_BRICK_WALL = register(new Block("stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block MUD_BRICK_WALL = register(new Block("mud_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block NETHER_BRICK_WALL = register(new Block("nether_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block ANDESITE_WALL = register(new Block("andesite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block RED_NETHER_BRICK_WALL = register(new Block("red_nether_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block SANDSTONE_WALL = register(new Block("sandstone_wall", builder().requiresCorrectToolForDrops().destroyTime(0.8f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block END_STONE_BRICK_WALL = register(new Block("end_stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block DIORITE_WALL = register(new Block("diorite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block SCAFFOLDING = register(new Block("scaffolding", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(BOTTOM)
+ .intState(STABILITY_DISTANCE)
+ .booleanState(WATERLOGGED)));
+ public static final Block LOOM = register(new Block("loom", builder().destroyTime(2.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BARREL = register(new Block("barrel", builder().setBlockEntity().destroyTime(2.5f)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(OPEN)));
+ public static final Block SMOKER = register(new Block("smoker", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)));
+ public static final Block BLAST_FURNACE = register(new Block("blast_furnace", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)));
+ public static final Block CARTOGRAPHY_TABLE = register(new Block("cartography_table", builder().destroyTime(2.5f)));
+ public static final Block FLETCHING_TABLE = register(new Block("fletching_table", builder().destroyTime(2.5f)));
+ public static final Block GRINDSTONE = register(new Block("grindstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f).pushReaction(PistonBehavior.BLOCK)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block LECTERN = register(new LecternBlock("lectern", builder().setBlockEntity().destroyTime(2.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(HAS_BOOK)
+ .booleanState(POWERED)));
+ public static final Block SMITHING_TABLE = register(new Block("smithing_table", builder().destroyTime(2.5f)));
+ public static final Block STONECUTTER = register(new Block("stonecutter", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
+ public static final Block BELL = register(new Block("bell", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(BELL_ATTACHMENT)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block LANTERN = register(new Block("lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(HANGING)
+ .booleanState(WATERLOGGED)));
+ public static final Block SOUL_LANTERN = register(new Block("soul_lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(HANGING)
+ .booleanState(WATERLOGGED)));
+ public static final Block CAMPFIRE = register(new Block("campfire", builder().setBlockEntity().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)
+ .booleanState(SIGNAL_FIRE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SOUL_CAMPFIRE = register(new Block("soul_campfire", builder().setBlockEntity().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(LIT)
+ .booleanState(SIGNAL_FIRE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SWEET_BERRY_BUSH = register(new Block("sweet_berry_bush", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_3)));
+ public static final Block WARPED_STEM = register(new Block("warped_stem", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_WARPED_STEM = register(new Block("stripped_warped_stem", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block WARPED_HYPHAE = register(new Block("warped_hyphae", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_WARPED_HYPHAE = register(new Block("stripped_warped_hyphae", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block WARPED_NYLIUM = register(new Block("warped_nylium", builder().requiresCorrectToolForDrops().destroyTime(0.4f)));
+ public static final Block WARPED_FUNGUS = register(new Block("warped_fungus", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block WARPED_WART_BLOCK = register(new Block("warped_wart_block", builder().destroyTime(1.0f)));
+ public static final Block WARPED_ROOTS = register(new Block("warped_roots", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block NETHER_SPROUTS = register(new Block("nether_sprouts", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block CRIMSON_STEM = register(new Block("crimson_stem", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_CRIMSON_STEM = register(new Block("stripped_crimson_stem", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block CRIMSON_HYPHAE = register(new Block("crimson_hyphae", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block STRIPPED_CRIMSON_HYPHAE = register(new Block("stripped_crimson_hyphae", builder().destroyTime(2.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block CRIMSON_NYLIUM = register(new Block("crimson_nylium", builder().requiresCorrectToolForDrops().destroyTime(0.4f)));
+ public static final Block CRIMSON_FUNGUS = register(new Block("crimson_fungus", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block SHROOMLIGHT = register(new Block("shroomlight", builder().destroyTime(1.0f)));
+ public static final Block WEEPING_VINES = register(new Block("weeping_vines", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_25)));
+ public static final Block WEEPING_VINES_PLANT = register(new Block("weeping_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.WEEPING_VINES)));
+ public static final Block TWISTING_VINES = register(new Block("twisting_vines", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_25)));
+ public static final Block TWISTING_VINES_PLANT = register(new Block("twisting_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.TWISTING_VINES)));
+ public static final Block CRIMSON_ROOTS = register(new Block("crimson_roots", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block CRIMSON_PLANKS = register(new Block("crimson_planks", builder().destroyTime(2.0f)));
+ public static final Block WARPED_PLANKS = register(new Block("warped_planks", builder().destroyTime(2.0f)));
+ public static final Block CRIMSON_SLAB = register(new Block("crimson_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_SLAB = register(new Block("warped_slab", builder().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_PRESSURE_PLATE = register(new Block("crimson_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block WARPED_PRESSURE_PLATE = register(new Block("warped_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block CRIMSON_FENCE = register(new Block("crimson_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block WARPED_FENCE = register(new Block("warped_fence", builder().destroyTime(2.0f)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block CRIMSON_TRAPDOOR = register(new TrapDoorBlock("crimson_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_TRAPDOOR = register(new TrapDoorBlock("warped_trapdoor", builder().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_FENCE_GATE = register(new Block("crimson_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WARPED_FENCE_GATE = register(new Block("warped_fence_gate", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(IN_WALL)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block CRIMSON_STAIRS = register(new Block("crimson_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_STAIRS = register(new Block("warped_stairs", builder().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_BUTTON = register(new Block("crimson_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block WARPED_BUTTON = register(new Block("warped_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block CRIMSON_DOOR = register(new DoorBlock("crimson_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WARPED_DOOR = register(new DoorBlock("warped_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block CRIMSON_SIGN = register(new Block("crimson_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_SIGN = register(new Block("warped_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .intState(ROTATION_16)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRIMSON_WALL_SIGN = register(new Block("crimson_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block WARPED_WALL_SIGN = register(new Block("warped_wall_sign", builder().setBlockEntity().destroyTime(1.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block STRUCTURE_BLOCK = register(new Block("structure_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f)
+ .enumState(STRUCTUREBLOCK_MODE)));
+ public static final Block JIGSAW = register(new Block("jigsaw", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f)
+ .enumState(ORIENTATION, FrontAndTop.VALUES)));
+ public static final Block COMPOSTER = register(new Block("composter", builder().destroyTime(0.6f)
+ .intState(LEVEL_COMPOSTER)));
+ public static final Block TARGET = register(new Block("target", builder().destroyTime(0.5f)
+ .intState(POWER)));
+ public static final Block BEE_NEST = register(new Block("bee_nest", builder().setBlockEntity().destroyTime(0.3f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .intState(LEVEL_HONEY)));
+ public static final Block BEEHIVE = register(new Block("beehive", builder().setBlockEntity().destroyTime(0.6f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .intState(LEVEL_HONEY)));
+ public static final Block HONEY_BLOCK = register(new HoneyBlock("honey_block", builder()));
+ public static final Block HONEYCOMB_BLOCK = register(new Block("honeycomb_block", builder().destroyTime(0.6f)));
+ public static final Block NETHERITE_BLOCK = register(new Block("netherite_block", builder().requiresCorrectToolForDrops().destroyTime(50.0f)));
+ public static final Block ANCIENT_DEBRIS = register(new Block("ancient_debris", builder().requiresCorrectToolForDrops().destroyTime(30.0f)));
+ public static final Block CRYING_OBSIDIAN = register(new Block("crying_obsidian", builder().requiresCorrectToolForDrops().destroyTime(50.0f)));
+ public static final Block RESPAWN_ANCHOR = register(new Block("respawn_anchor", builder().requiresCorrectToolForDrops().destroyTime(50.0f)
+ .intState(RESPAWN_ANCHOR_CHARGES)));
+ public static final Block POTTED_CRIMSON_FUNGUS = register(new FlowerPotBlock("potted_crimson_fungus", CRIMSON_FUNGUS, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_WARPED_FUNGUS = register(new FlowerPotBlock("potted_warped_fungus", WARPED_FUNGUS, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_CRIMSON_ROOTS = register(new FlowerPotBlock("potted_crimson_roots", CRIMSON_ROOTS, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_WARPED_ROOTS = register(new FlowerPotBlock("potted_warped_roots", WARPED_ROOTS, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block LODESTONE = register(new Block("lodestone", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.BLOCK)));
+ public static final Block BLACKSTONE = register(new Block("blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block BLACKSTONE_STAIRS = register(new Block("blackstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block BLACKSTONE_WALL = register(new Block("blackstone_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block BLACKSTONE_SLAB = register(new Block("blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_BLACKSTONE = register(new Block("polished_blackstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block POLISHED_BLACKSTONE_BRICKS = register(new Block("polished_blackstone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new Block("cracked_polished_blackstone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CHISELED_POLISHED_BLACKSTONE = register(new Block("chiseled_polished_blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_BLACKSTONE_BRICK_SLAB = register(new Block("polished_blackstone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_BLACKSTONE_BRICK_STAIRS = register(new Block("polished_blackstone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_BLACKSTONE_BRICK_WALL = register(new Block("polished_blackstone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block GILDED_BLACKSTONE = register(new Block("gilded_blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_BLACKSTONE_STAIRS = register(new Block("polished_blackstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_BLACKSTONE_SLAB = register(new Block("polished_blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(POWERED)));
+ public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(ATTACH_FACE)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(POWERED)));
+ public static final Block POLISHED_BLACKSTONE_WALL = register(new Block("polished_blackstone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block CHISELED_NETHER_BRICKS = register(new Block("chiseled_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block CRACKED_NETHER_BRICKS = register(new Block("cracked_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
+ public static final Block QUARTZ_BRICKS = register(new Block("quartz_bricks", builder().requiresCorrectToolForDrops().destroyTime(0.8f)));
+ public static final Block CANDLE = register(new Block("candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block WHITE_CANDLE = register(new Block("white_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block ORANGE_CANDLE = register(new Block("orange_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block MAGENTA_CANDLE = register(new Block("magenta_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block LIGHT_BLUE_CANDLE = register(new Block("light_blue_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block YELLOW_CANDLE = register(new Block("yellow_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block LIME_CANDLE = register(new Block("lime_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block PINK_CANDLE = register(new Block("pink_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block GRAY_CANDLE = register(new Block("gray_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block LIGHT_GRAY_CANDLE = register(new Block("light_gray_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block CYAN_CANDLE = register(new Block("cyan_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block PURPLE_CANDLE = register(new Block("purple_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block BLUE_CANDLE = register(new Block("blue_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block BROWN_CANDLE = register(new Block("brown_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block GREEN_CANDLE = register(new Block("green_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block RED_CANDLE = register(new Block("red_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block BLACK_CANDLE = register(new Block("black_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .intState(CANDLES)
+ .booleanState(LIT)
+ .booleanState(WATERLOGGED)));
+ public static final Block CANDLE_CAKE = register(new Block("candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block WHITE_CANDLE_CAKE = register(new Block("white_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block ORANGE_CANDLE_CAKE = register(new Block("orange_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block MAGENTA_CANDLE_CAKE = register(new Block("magenta_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block LIGHT_BLUE_CANDLE_CAKE = register(new Block("light_blue_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block YELLOW_CANDLE_CAKE = register(new Block("yellow_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block LIME_CANDLE_CAKE = register(new Block("lime_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block PINK_CANDLE_CAKE = register(new Block("pink_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block GRAY_CANDLE_CAKE = register(new Block("gray_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block LIGHT_GRAY_CANDLE_CAKE = register(new Block("light_gray_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block CYAN_CANDLE_CAKE = register(new Block("cyan_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block PURPLE_CANDLE_CAKE = register(new Block("purple_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block BLUE_CANDLE_CAKE = register(new Block("blue_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block BROWN_CANDLE_CAKE = register(new Block("brown_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block GREEN_CANDLE_CAKE = register(new Block("green_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block RED_CANDLE_CAKE = register(new Block("red_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block BLACK_CANDLE_CAKE = register(new Block("black_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE)
+ .booleanState(LIT)));
+ public static final Block AMETHYST_BLOCK = register(new Block("amethyst_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block BUDDING_AMETHYST = register(new Block("budding_amethyst", builder().requiresCorrectToolForDrops().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block AMETHYST_CLUSTER = register(new Block("amethyst_cluster", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(WATERLOGGED)));
+ public static final Block LARGE_AMETHYST_BUD = register(new Block("large_amethyst_bud", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(WATERLOGGED)));
+ public static final Block MEDIUM_AMETHYST_BUD = register(new Block("medium_amethyst_bud", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMALL_AMETHYST_BUD = register(new Block("small_amethyst_bud", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUFF = register(new Block("tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block TUFF_SLAB = register(new Block("tuff_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUFF_STAIRS = register(new Block("tuff_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUFF_WALL = register(new Block("tuff_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block POLISHED_TUFF = register(new Block("polished_tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block POLISHED_TUFF_SLAB = register(new Block("polished_tuff_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_TUFF_STAIRS = register(new Block("polished_tuff_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_TUFF_WALL = register(new Block("polished_tuff_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block CHISELED_TUFF = register(new Block("chiseled_tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block TUFF_BRICKS = register(new Block("tuff_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block TUFF_BRICK_SLAB = register(new Block("tuff_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUFF_BRICK_STAIRS = register(new Block("tuff_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block TUFF_BRICK_WALL = register(new Block("tuff_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block CHISELED_TUFF_BRICKS = register(new Block("chiseled_tuff_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CALCITE = register(new Block("calcite", builder().requiresCorrectToolForDrops().destroyTime(0.75f)));
+ public static final Block TINTED_GLASS = register(new Block("tinted_glass", builder().destroyTime(0.3f)));
+ public static final Block POWDER_SNOW = register(new Block("powder_snow", builder().destroyTime(0.25f)));
+ public static final Block SCULK_SENSOR = register(new Block("sculk_sensor", builder().setBlockEntity().destroyTime(1.5f)
+ .intState(POWER)
+ .enumState(SCULK_SENSOR_PHASE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CALIBRATED_SCULK_SENSOR = register(new Block("calibrated_sculk_sensor", builder().setBlockEntity().destroyTime(1.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .intState(POWER)
+ .enumState(SCULK_SENSOR_PHASE)
+ .booleanState(WATERLOGGED)));
+ public static final Block SCULK = register(new Block("sculk", builder().destroyTime(0.2f)));
+ public static final Block SCULK_VEIN = register(new Block("sculk_vein", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
+ .booleanState(DOWN)
+ .booleanState(EAST)
+ .booleanState(NORTH)
+ .booleanState(SOUTH)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .booleanState(WEST)));
+ public static final Block SCULK_CATALYST = register(new Block("sculk_catalyst", builder().setBlockEntity().destroyTime(3.0f)
+ .booleanState(BLOOM)));
+ public static final Block SCULK_SHRIEKER = register(new Block("sculk_shrieker", builder().setBlockEntity().destroyTime(3.0f)
+ .booleanState(CAN_SUMMON)
+ .booleanState(SHRIEKING)
+ .booleanState(WATERLOGGED)));
+ public static final Block COPPER_BLOCK = register(new Block("copper_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block EXPOSED_COPPER = register(new Block("exposed_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WEATHERED_COPPER = register(new Block("weathered_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block OXIDIZED_COPPER = register(new Block("oxidized_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block COPPER_ORE = register(new Block("copper_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block DEEPSLATE_COPPER_ORE = register(new Block("deepslate_copper_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
+ public static final Block OXIDIZED_CUT_COPPER = register(new Block("oxidized_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WEATHERED_CUT_COPPER = register(new Block("weathered_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block EXPOSED_CUT_COPPER = register(new Block("exposed_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block CUT_COPPER = register(new Block("cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block OXIDIZED_CHISELED_COPPER = register(new Block("oxidized_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WEATHERED_CHISELED_COPPER = register(new Block("weathered_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block EXPOSED_CHISELED_COPPER = register(new Block("exposed_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block CHISELED_COPPER = register(new Block("chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_OXIDIZED_CHISELED_COPPER = register(new Block("waxed_oxidized_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_WEATHERED_CHISELED_COPPER = register(new Block("waxed_weathered_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_EXPOSED_CHISELED_COPPER = register(new Block("waxed_exposed_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_CHISELED_COPPER = register(new Block("waxed_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block OXIDIZED_CUT_COPPER_STAIRS = register(new Block("oxidized_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WEATHERED_CUT_COPPER_STAIRS = register(new Block("weathered_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block EXPOSED_CUT_COPPER_STAIRS = register(new Block("exposed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CUT_COPPER_STAIRS = register(new Block("cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block OXIDIZED_CUT_COPPER_SLAB = register(new Block("oxidized_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WEATHERED_CUT_COPPER_SLAB = register(new Block("weathered_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block EXPOSED_CUT_COPPER_SLAB = register(new Block("exposed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block CUT_COPPER_SLAB = register(new Block("cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_COPPER_BLOCK = register(new Block("waxed_copper_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_WEATHERED_COPPER = register(new Block("waxed_weathered_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_EXPOSED_COPPER = register(new Block("waxed_exposed_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_OXIDIZED_COPPER = register(new Block("waxed_oxidized_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_OXIDIZED_CUT_COPPER = register(new Block("waxed_oxidized_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_WEATHERED_CUT_COPPER = register(new Block("waxed_weathered_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_EXPOSED_CUT_COPPER = register(new Block("waxed_exposed_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_CUT_COPPER = register(new Block("waxed_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
+ public static final Block WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new Block("waxed_oxidized_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new Block("waxed_weathered_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new Block("waxed_exposed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_CUT_COPPER_STAIRS = register(new Block("waxed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new Block("waxed_oxidized_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_WEATHERED_CUT_COPPER_SLAB = register(new Block("waxed_weathered_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_EXPOSED_CUT_COPPER_SLAB = register(new Block("waxed_exposed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_CUT_COPPER_SLAB = register(new Block("waxed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COPPER_DOOR = register(new DoorBlock("copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block EXPOSED_COPPER_DOOR = register(new DoorBlock("exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block OXIDIZED_COPPER_DOOR = register(new DoorBlock("oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WEATHERED_COPPER_DOOR = register(new DoorBlock("weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WAXED_COPPER_DOOR = register(new DoorBlock("waxed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WAXED_EXPOSED_COPPER_DOOR = register(new DoorBlock("waxed_exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WAXED_OXIDIZED_COPPER_DOOR = register(new DoorBlock("waxed_oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block WAXED_WEATHERED_COPPER_DOOR = register(new DoorBlock("waxed_weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .enumState(DOOR_HINGE)
+ .booleanState(OPEN)
+ .booleanState(POWERED)));
+ public static final Block COPPER_TRAPDOOR = register(new TrapDoorBlock("copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block EXPOSED_COPPER_TRAPDOOR = register(new TrapDoorBlock("exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block OXIDIZED_COPPER_TRAPDOOR = register(new TrapDoorBlock("oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WEATHERED_COPPER_TRAPDOOR = register(new TrapDoorBlock("weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_EXPOSED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_WEATHERED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .booleanState(OPEN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block COPPER_GRATE = register(new Block("copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block EXPOSED_COPPER_GRATE = register(new Block("exposed_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block WEATHERED_COPPER_GRATE = register(new Block("weathered_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block OXIDIZED_COPPER_GRATE = register(new Block("oxidized_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_COPPER_GRATE = register(new Block("waxed_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_EXPOSED_COPPER_GRATE = register(new Block("waxed_exposed_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_WEATHERED_COPPER_GRATE = register(new Block("waxed_weathered_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block WAXED_OXIDIZED_COPPER_GRATE = register(new Block("waxed_oxidized_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(WATERLOGGED)));
+ public static final Block COPPER_BULB = register(new Block("copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block EXPOSED_COPPER_BULB = register(new Block("exposed_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block WEATHERED_COPPER_BULB = register(new Block("weathered_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block OXIDIZED_COPPER_BULB = register(new Block("oxidized_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block WAXED_COPPER_BULB = register(new Block("waxed_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block WAXED_EXPOSED_COPPER_BULB = register(new Block("waxed_exposed_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block WAXED_WEATHERED_COPPER_BULB = register(new Block("waxed_weathered_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block WAXED_OXIDIZED_COPPER_BULB = register(new Block("waxed_oxidized_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .booleanState(LIT)
+ .booleanState(POWERED)));
+ public static final Block LIGHTNING_ROD = register(new Block("lightning_rod", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN)
+ .booleanState(POWERED)
+ .booleanState(WATERLOGGED)));
+ public static final Block POINTED_DRIPSTONE = register(new Block("pointed_dripstone", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(DRIPSTONE_THICKNESS)
+ .enumState(VERTICAL_DIRECTION, Direction.UP, Direction.DOWN)
+ .booleanState(WATERLOGGED)));
+ public static final Block DRIPSTONE_BLOCK = register(new Block("dripstone_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
+ public static final Block CAVE_VINES = register(new Block("cave_vines", builder().pushReaction(PistonBehavior.DESTROY)
+ .intState(AGE_25)
+ .booleanState(BERRIES)));
+ public static final Block CAVE_VINES_PLANT = register(new Block("cave_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.GLOW_BERRIES)
+ .booleanState(BERRIES)));
+ public static final Block SPORE_BLOSSOM = register(new Block("spore_blossom", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block AZALEA = register(new Block("azalea", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block FLOWERING_AZALEA = register(new Block("flowering_azalea", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block MOSS_CARPET = register(new Block("moss_carpet", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block PINK_PETALS = register(new Block("pink_petals", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .intState(FLOWER_AMOUNT)));
+ public static final Block MOSS_BLOCK = register(new Block("moss_block", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)));
+ public static final Block BIG_DRIPLEAF = register(new Block("big_dripleaf", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(TILT)
+ .booleanState(WATERLOGGED)));
+ public static final Block BIG_DRIPLEAF_STEM = register(new Block("big_dripleaf_stem", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block SMALL_DRIPLEAF = register(new Block("small_dripleaf", builder().pushReaction(PistonBehavior.DESTROY)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(DOUBLE_BLOCK_HALF)
+ .booleanState(WATERLOGGED)));
+ public static final Block HANGING_ROOTS = register(new Block("hanging_roots", builder().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(WATERLOGGED)));
+ public static final Block ROOTED_DIRT = register(new Block("rooted_dirt", builder().destroyTime(0.5f)));
+ public static final Block MUD = register(new Block("mud", builder().destroyTime(0.5f)));
+ public static final Block DEEPSLATE = register(new Block("deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block COBBLED_DEEPSLATE = register(new Block("cobbled_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block COBBLED_DEEPSLATE_STAIRS = register(new Block("cobbled_deepslate_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COBBLED_DEEPSLATE_SLAB = register(new Block("cobbled_deepslate_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block COBBLED_DEEPSLATE_WALL = register(new Block("cobbled_deepslate_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block POLISHED_DEEPSLATE = register(new Block("polished_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block POLISHED_DEEPSLATE_STAIRS = register(new Block("polished_deepslate_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_DEEPSLATE_SLAB = register(new Block("polished_deepslate_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block POLISHED_DEEPSLATE_WALL = register(new Block("polished_deepslate_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block DEEPSLATE_TILES = register(new Block("deepslate_tiles", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block DEEPSLATE_TILE_STAIRS = register(new Block("deepslate_tile_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEEPSLATE_TILE_SLAB = register(new Block("deepslate_tile_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEEPSLATE_TILE_WALL = register(new Block("deepslate_tile_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block DEEPSLATE_BRICKS = register(new Block("deepslate_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block DEEPSLATE_BRICK_STAIRS = register(new Block("deepslate_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .enumState(HALF)
+ .enumState(STAIRS_SHAPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEEPSLATE_BRICK_SLAB = register(new Block("deepslate_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(SLAB_TYPE)
+ .booleanState(WATERLOGGED)));
+ public static final Block DEEPSLATE_BRICK_WALL = register(new Block("deepslate_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
+ .enumState(EAST_WALL)
+ .enumState(NORTH_WALL)
+ .enumState(SOUTH_WALL)
+ .booleanState(UP)
+ .booleanState(WATERLOGGED)
+ .enumState(WEST_WALL)));
+ public static final Block CHISELED_DEEPSLATE = register(new Block("chiseled_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block CRACKED_DEEPSLATE_BRICKS = register(new Block("cracked_deepslate_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block CRACKED_DEEPSLATE_TILES = register(new Block("cracked_deepslate_tiles", builder().requiresCorrectToolForDrops().destroyTime(3.5f)));
+ public static final Block INFESTED_DEEPSLATE = register(new Block("infested_deepslate", builder().destroyTime(1.5f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block SMOOTH_BASALT = register(new Block("smooth_basalt", builder().requiresCorrectToolForDrops().destroyTime(1.25f)));
+ public static final Block RAW_IRON_BLOCK = register(new Block("raw_iron_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block RAW_COPPER_BLOCK = register(new Block("raw_copper_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block RAW_GOLD_BLOCK = register(new Block("raw_gold_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f)));
+ public static final Block POTTED_AZALEA_BUSH = register(new FlowerPotBlock("potted_azalea_bush", AZALEA, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block POTTED_FLOWERING_AZALEA_BUSH = register(new FlowerPotBlock("potted_flowering_azalea_bush", FLOWERING_AZALEA, builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block OCHRE_FROGLIGHT = register(new Block("ochre_froglight", builder().destroyTime(0.3f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block VERDANT_FROGLIGHT = register(new Block("verdant_froglight", builder().destroyTime(0.3f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block PEARLESCENT_FROGLIGHT = register(new Block("pearlescent_froglight", builder().destroyTime(0.3f)
+ .enumState(AXIS, Axis.VALUES)));
+ public static final Block FROGSPAWN = register(new Block("frogspawn", builder().pushReaction(PistonBehavior.DESTROY)));
+ public static final Block REINFORCED_DEEPSLATE = register(new Block("reinforced_deepslate", builder().destroyTime(55.0f)));
+ public static final Block DECORATED_POT = register(new Block("decorated_pot", builder().setBlockEntity().pushReaction(PistonBehavior.DESTROY)
+ .booleanState(CRACKED)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(WATERLOGGED)));
+ public static final Block CRAFTER = register(new Block("crafter", builder().setBlockEntity().destroyTime(1.5f)
+ .booleanState(CRAFTING)
+ .enumState(ORIENTATION, FrontAndTop.VALUES)
+ .booleanState(TRIGGERED)));
+ public static final Block TRIAL_SPAWNER = register(new Block("trial_spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(50.0f)
+ .booleanState(OMINOUS)
+ .enumState(TRIAL_SPAWNER_STATE)));
+ public static final Block VAULT = register(new Block("vault", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(50.0f)
+ .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
+ .booleanState(OMINOUS)
+ .enumState(VAULT_STATE)));
+ public static final Block HEAVY_CORE = register(new Block("heavy_core", builder().destroyTime(10.0f)
+ .booleanState(WATERLOGGED)));
+
+ private static T register(T block) {
+ block.setJavaId(BlockRegistries.JAVA_BLOCKS.get().size());
+ BlockRegistries.JAVA_BLOCKS.get().add(block);
+ return block;
+ }
+
+ private Blocks() {
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java
new file mode 100644
index 000000000..c34392504
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.property;
+
+import java.util.List;
+
+/**
+ * Represents enums we don't need classes for in Geyser.
+ */
+public final class BasicEnumProperty extends Property {
+ private final List values;
+
+ private BasicEnumProperty(String name, List values) {
+ super(name);
+ this.values = values;
+ }
+
+ @Override
+ public int valuesCount() {
+ return this.values.size();
+ }
+
+ @Override
+ public int indexOf(String value) {
+ int index = this.values.indexOf(value);
+ if (index == -1) {
+ throw new IllegalArgumentException("Property " + this + " does not have value " + value);
+ }
+ return index;
+ }
+
+ @SuppressWarnings("unchecked")
+ public T values() {
+ return (T) this.values;
+ }
+
+ public static BasicEnumProperty create(String name, String... values) {
+ return new BasicEnumProperty(name, List.of(values));
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/util/collection/package-info.java b/core/src/main/java/org/geysermc/geyser/level/block/property/BooleanProperty.java
similarity index 65%
rename from core/src/main/java/org/geysermc/geyser/util/collection/package-info.java
rename to core/src/main/java/org/geysermc/geyser/level/block/property/BooleanProperty.java
index 46fa5df11..56877f537 100644
--- a/core/src/main/java/org/geysermc/geyser/util/collection/package-info.java
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/BooleanProperty.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,12 +23,24 @@
* @link https://github.com/GeyserMC/Geyser
*/
-/**
- * Contains useful collections for use in Geyser.
- *
- * Of note are the fixed int maps. Designed for use with block states that are positive and sequential, they do not allow keys to be
- * added that are not greater by one versus the previous key. Because of this, speedy operations of {@link java.util.Map#get(java.lang.Object)}
- * and {@link java.util.Map#containsKey(java.lang.Object)} can be performed by simply checking the bounds of the map
- * size and its "start" integer.
- */
-package org.geysermc.geyser.util.collection;
\ No newline at end of file
+package org.geysermc.geyser.level.block.property;
+
+public final class BooleanProperty extends Property {
+ private BooleanProperty(String name) {
+ super(name);
+ }
+
+ @Override
+ public int valuesCount() {
+ return 2;
+ }
+
+ @Override
+ public int indexOf(Boolean value) {
+ return value ? 0 : 1;
+ }
+
+ public static BooleanProperty create(String name) {
+ return new BooleanProperty(name);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java b/core/src/main/java/org/geysermc/geyser/level/block/property/ChestType.java
similarity index 65%
rename from core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java
rename to core/src/main/java/org/geysermc/geyser/level/block/property/ChestType.java
index 97c861df7..c206f127c 100644
--- a/core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/ChestType.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,18 +23,12 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.geyser.level.block;
+package org.geysermc.geyser.level.block.property;
-/**
- * This stores all values of double chests that are part of the Java block state.
- *
- * @param isFacingEast If true, then chest is facing east/west; if false, south/north
- * @param isDirectionPositive If true, direction is positive (east/south); if false, direction is negative (west/north)
- * @param isLeft If true, chest is the left of a pair; if false, chest is the right of a pair.
- */
-public record DoubleChestValue(
- boolean isFacingEast,
- boolean isDirectionPositive,
- boolean isLeft) {
+public enum ChestType {
+ SINGLE,
+ LEFT,
+ RIGHT;
+ public static final ChestType[] VALUES = values();
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/EnumProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/EnumProperty.java
new file mode 100644
index 000000000..e31f665f9
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/EnumProperty.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.property;
+
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.ints.IntList;
+
+public final class EnumProperty> extends Property {
+ private final IntList ordinalValues;
+
+ /**
+ * @param values all possible values of this enum.
+ */
+ private EnumProperty(String name, T[] values) {
+ super(name);
+ this.ordinalValues = new IntArrayList(values.length);
+ for (T anEnum : values) {
+ this.ordinalValues.add(anEnum.ordinal());
+ }
+ }
+
+ @Override
+ public int valuesCount() {
+ return this.ordinalValues.size();
+ }
+
+ @Override
+ public int indexOf(T value) {
+ return this.ordinalValues.indexOf(value.ordinal());
+ }
+
+ @SafeVarargs
+ public static > EnumProperty create(String name, T... values) {
+ return new EnumProperty<>(name, values);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/FrontAndTop.java b/core/src/main/java/org/geysermc/geyser/level/block/property/FrontAndTop.java
new file mode 100644
index 000000000..e674ac424
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/FrontAndTop.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.property;
+
+import org.geysermc.geyser.level.physics.Direction;
+
+public enum FrontAndTop {
+ DOWN_EAST(Direction.DOWN),
+ DOWN_NORTH(Direction.DOWN),
+ DOWN_SOUTH(Direction.DOWN),
+ DOWN_WEST(Direction.DOWN),
+ UP_EAST(Direction.UP),
+ UP_NORTH(Direction.UP),
+ UP_SOUTH(Direction.UP),
+ UP_WEST(Direction.UP),
+ WEST_UP(Direction.WEST),
+ EAST_UP(Direction.EAST),
+ NORTH_UP(Direction.NORTH),
+ SOUTH_UP(Direction.SOUTH);
+
+ private final boolean horizontal;
+
+ FrontAndTop(Direction front) {
+ this.horizontal = front.isHorizontal();
+ }
+
+ public boolean isHorizontal() {
+ return horizontal;
+ }
+
+ public static final FrontAndTop[] VALUES = values();
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/IntegerProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/IntegerProperty.java
new file mode 100644
index 000000000..a772f414d
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/IntegerProperty.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.property;
+
+public final class IntegerProperty extends Property {
+ private final int offset;
+ private final int valuesCount;
+
+ private IntegerProperty(String name, int low, int high) {
+ super(name);
+ this.offset = low;
+ this.valuesCount = high - low;
+ }
+
+ @Override
+ public int valuesCount() {
+ return this.valuesCount;
+ }
+
+ @Override
+ public int indexOf(Integer value) {
+ return value - this.offset;
+ }
+
+ public int low() {
+ return this.offset;
+ }
+
+ public int high() {
+ return this.offset + this.valuesCount;
+ }
+
+ public static IntegerProperty create(String name, int low, int high) {
+ return new IntegerProperty(name, low, high);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java
new file mode 100644
index 000000000..7efa2ef80
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.property;
+
+import org.geysermc.geyser.level.physics.Axis;
+import org.geysermc.geyser.level.physics.Direction;
+
+public final class Properties {
+ public static final BooleanProperty ATTACHED = BooleanProperty.create("attached");
+ public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom");
+ public static final BooleanProperty CONDITIONAL = BooleanProperty.create("conditional");
+ public static final BooleanProperty DISARMED = BooleanProperty.create("disarmed");
+ public static final BooleanProperty DRAG = BooleanProperty.create("drag");
+ public static final BooleanProperty ENABLED = BooleanProperty.create("enabled");
+ public static final BooleanProperty EXTENDED = BooleanProperty.create("extended");
+ public static final BooleanProperty EYE = BooleanProperty.create("eye");
+ public static final BooleanProperty FALLING = BooleanProperty.create("falling");
+ public static final BooleanProperty HANGING = BooleanProperty.create("hanging");
+ public static final BooleanProperty HAS_BOTTLE_0 = BooleanProperty.create("has_bottle_0");
+ public static final BooleanProperty HAS_BOTTLE_1 = BooleanProperty.create("has_bottle_1");
+ public static final BooleanProperty HAS_BOTTLE_2 = BooleanProperty.create("has_bottle_2");
+ public static final BooleanProperty HAS_RECORD = BooleanProperty.create("has_record");
+ public static final BooleanProperty HAS_BOOK = BooleanProperty.create("has_book");
+ public static final BooleanProperty INVERTED = BooleanProperty.create("inverted");
+ public static final BooleanProperty IN_WALL = BooleanProperty.create("in_wall");
+ public static final BooleanProperty LIT = BooleanProperty.create("lit");
+ public static final BooleanProperty LOCKED = BooleanProperty.create("locked");
+ public static final BooleanProperty OCCUPIED = BooleanProperty.create("occupied");
+ public static final BooleanProperty OPEN = BooleanProperty.create("open");
+ public static final BooleanProperty PERSISTENT = BooleanProperty.create("persistent");
+ public static final BooleanProperty POWERED = BooleanProperty.create("powered");
+ public static final BooleanProperty SHORT = BooleanProperty.create("short");
+ public static final BooleanProperty SIGNAL_FIRE = BooleanProperty.create("signal_fire");
+ public static final BooleanProperty SNOWY = BooleanProperty.create("snowy");
+ public static final BooleanProperty TRIGGERED = BooleanProperty.create("triggered");
+ public static final BooleanProperty UNSTABLE = BooleanProperty.create("unstable");
+ public static final BooleanProperty WATERLOGGED = BooleanProperty.create("waterlogged");
+ public static final BooleanProperty BERRIES = BooleanProperty.create("berries");
+ public static final BooleanProperty BLOOM = BooleanProperty.create("bloom");
+ public static final BooleanProperty SHRIEKING = BooleanProperty.create("shrieking");
+ public static final BooleanProperty CAN_SUMMON = BooleanProperty.create("can_summon");
+ public static final EnumProperty HORIZONTAL_AXIS = EnumProperty.create("axis", Axis.X, Axis.Z);
+ public static final EnumProperty AXIS = EnumProperty.create("axis", Axis.VALUES);
+ public static final BooleanProperty UP = BooleanProperty.create("up");
+ public static final BooleanProperty DOWN = BooleanProperty.create("down");
+ public static final BooleanProperty NORTH = BooleanProperty.create("north");
+ public static final BooleanProperty EAST = BooleanProperty.create("east");
+ public static final BooleanProperty SOUTH = BooleanProperty.create("south");
+ public static final BooleanProperty WEST = BooleanProperty.create("west");
+ public static final EnumProperty FACING = EnumProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN);
+ public static final EnumProperty FACING_HOPPER = EnumProperty.create("facing", Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST);
+ public static final EnumProperty HORIZONTAL_FACING = EnumProperty.create("facing", Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST);
+ public static final IntegerProperty FLOWER_AMOUNT = IntegerProperty.create("flower_amount", 1, 4);
+ public static final EnumProperty ORIENTATION = EnumProperty.create("orientation", FrontAndTop.VALUES);
+ public static final BasicEnumProperty ATTACH_FACE = BasicEnumProperty.create("face", "floor", "wall", "ceiling");
+ public static final BasicEnumProperty BELL_ATTACHMENT = BasicEnumProperty.create("attachment", "floor", "ceiling", "single_wall", "double_wall");
+ public static final BasicEnumProperty EAST_WALL = BasicEnumProperty.create("east", "none", "low", "tall");
+ public static final BasicEnumProperty NORTH_WALL = BasicEnumProperty.create("north", "none", "low", "tall");
+ public static final BasicEnumProperty SOUTH_WALL = BasicEnumProperty.create("south", "none", "low", "tall");
+ public static final BasicEnumProperty WEST_WALL = BasicEnumProperty.create("west", "none", "low", "tall");
+ public static final BasicEnumProperty EAST_REDSTONE = BasicEnumProperty.create("east", "up", "side", "none");
+ public static final BasicEnumProperty NORTH_REDSTONE = BasicEnumProperty.create("north", "up", "side", "none");
+ public static final BasicEnumProperty SOUTH_REDSTONE = BasicEnumProperty.create("south", "up", "side", "none");
+ public static final BasicEnumProperty WEST_REDSTONE = BasicEnumProperty.create("west", "up", "side", "none");
+ public static final BasicEnumProperty DOUBLE_BLOCK_HALF = BasicEnumProperty.create("half", "upper", "lower");
+ public static final BasicEnumProperty HALF = BasicEnumProperty.create("half", "top", "bottom");
+ public static final BasicEnumProperty RAIL_SHAPE = BasicEnumProperty.create("shape", "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south", "south_east", "south_west", "north_west", "north_east");
+ public static final BasicEnumProperty RAIL_SHAPE_STRAIGHT = BasicEnumProperty.create("shape", "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south");
+ public static final IntegerProperty AGE_1 = IntegerProperty.create("age", 0, 1);
+ public static final IntegerProperty AGE_2 = IntegerProperty.create("age", 0, 2);
+ public static final IntegerProperty AGE_3 = IntegerProperty.create("age", 0, 3);
+ public static final IntegerProperty AGE_4 = IntegerProperty.create("age", 0, 4);
+ public static final IntegerProperty AGE_5 = IntegerProperty.create("age", 0, 5);
+ public static final IntegerProperty AGE_7 = IntegerProperty.create("age", 0, 7);
+ public static final IntegerProperty AGE_15 = IntegerProperty.create("age", 0, 15);
+ public static final IntegerProperty AGE_25 = IntegerProperty.create("age", 0, 25);
+ public static final IntegerProperty BITES = IntegerProperty.create("bites", 0, 6);
+ public static final IntegerProperty CANDLES = IntegerProperty.create("candles", 1, 4);
+ public static final IntegerProperty DELAY = IntegerProperty.create("delay", 1, 4);
+ public static final IntegerProperty DISTANCE = IntegerProperty.create("distance", 1, 7);
+ public static final IntegerProperty EGGS = IntegerProperty.create("eggs", 1, 4);
+ public static final IntegerProperty HATCH = IntegerProperty.create("hatch", 0, 2);
+ public static final IntegerProperty LAYERS = IntegerProperty.create("layers", 1, 8);
+ public static final IntegerProperty LEVEL_CAULDRON = IntegerProperty.create("level", 1, 3);
+ public static final IntegerProperty LEVEL_COMPOSTER = IntegerProperty.create("level", 0, 8);
+ public static final IntegerProperty LEVEL_FLOWING = IntegerProperty.create("level", 1, 8);
+ public static final IntegerProperty LEVEL_HONEY = IntegerProperty.create("honey_level", 0, 5);
+ public static final IntegerProperty LEVEL = IntegerProperty.create("level", 0, 15);
+ public static final IntegerProperty MOISTURE = IntegerProperty.create("moisture", 0, 7);
+ public static final IntegerProperty NOTE = IntegerProperty.create("note", 0, 24);
+ public static final IntegerProperty PICKLES = IntegerProperty.create("pickles", 1, 4);
+ public static final IntegerProperty POWER = IntegerProperty.create("power", 0, 15);
+ public static final IntegerProperty STAGE = IntegerProperty.create("stage", 0, 1);
+ public static final IntegerProperty STABILITY_DISTANCE = IntegerProperty.create("distance", 0, 7);
+ public static final IntegerProperty RESPAWN_ANCHOR_CHARGES = IntegerProperty.create("charges", 0, 4);
+ public static final IntegerProperty ROTATION_16 = IntegerProperty.create("rotation", 0, 15);
+ public static final BasicEnumProperty BED_PART = BasicEnumProperty.create("part", "head", "foot");
+ public static final EnumProperty CHEST_TYPE = EnumProperty.create("type", ChestType.VALUES);
+ public static final BasicEnumProperty MODE_COMPARATOR = BasicEnumProperty.create("mode", "compare", "subtract");
+ public static final BasicEnumProperty DOOR_HINGE = BasicEnumProperty.create("hinge", "left", "right");
+ public static final BasicEnumProperty NOTEBLOCK_INSTRUMENT = BasicEnumProperty.create("instrument", "harp", "basedrum", "snare", "hat", "bass", "flute", "bell", "guitar", "chime", "xylophone", "iron_xylophone", "cow_bell", "didgeridoo", "bit", "banjo", "pling", "zombie", "skeleton", "creeper", "dragon", "wither_skeleton", "piglin", "custom_head");
+ public static final BasicEnumProperty PISTON_TYPE = BasicEnumProperty.create("type", "normal", "sticky");
+ public static final BasicEnumProperty SLAB_TYPE = BasicEnumProperty.create("type", "top", "bottom", "double");
+ public static final BasicEnumProperty STAIRS_SHAPE = BasicEnumProperty.create("shape", "straight", "inner_left", "inner_right", "outer_left", "outer_right");
+ public static final BasicEnumProperty STRUCTUREBLOCK_MODE = BasicEnumProperty.create("mode", "save", "load", "corner", "data");
+ public static final BasicEnumProperty BAMBOO_LEAVES = BasicEnumProperty.create("leaves", "none", "small", "large");
+ public static final BasicEnumProperty TILT = BasicEnumProperty.create("tilt", "none", "unstable", "partial", "full");
+ public static final EnumProperty VERTICAL_DIRECTION = EnumProperty.create("vertical_direction", Direction.UP, Direction.DOWN);
+ public static final BasicEnumProperty DRIPSTONE_THICKNESS = BasicEnumProperty.create("thickness", "tip_merge", "tip", "frustum", "middle", "base");
+ public static final BasicEnumProperty SCULK_SENSOR_PHASE = BasicEnumProperty.create("sculk_sensor_phase", "inactive", "active", "cooldown");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_0_OCCUPIED = BooleanProperty.create("slot_0_occupied");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_1_OCCUPIED = BooleanProperty.create("slot_1_occupied");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_2_OCCUPIED = BooleanProperty.create("slot_2_occupied");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_3_OCCUPIED = BooleanProperty.create("slot_3_occupied");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_4_OCCUPIED = BooleanProperty.create("slot_4_occupied");
+ public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_5_OCCUPIED = BooleanProperty.create("slot_5_occupied");
+ public static final IntegerProperty DUSTED = IntegerProperty.create("dusted", 0, 3);
+ public static final BooleanProperty CRACKED = BooleanProperty.create("cracked");
+ public static final BooleanProperty CRAFTING = BooleanProperty.create("crafting");
+ public static final BasicEnumProperty TRIAL_SPAWNER_STATE = BasicEnumProperty.create("trial_spawner_state", "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown");
+ public static final BasicEnumProperty VAULT_STATE = BasicEnumProperty.create("vault_state", "inactive", "active", "unlocking", "ejecting");
+ public static final BooleanProperty OMINOUS = BooleanProperty.create("ominous");
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java
new file mode 100644
index 000000000..0c4713124
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.property;
+
+public abstract class Property> {
+ private final String name;
+
+ protected Property(String name) {
+ this.name = name;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public abstract int valuesCount();
+
+ public abstract int indexOf(T value);
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[" + name + "]";
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BannerBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BannerBlock.java
new file mode 100644
index 000000000..481004baa
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BannerBlock.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+public class BannerBlock extends Block {
+ private final int dyeColor;
+
+ public BannerBlock(String javaIdentifier, int dyeColor, Builder builder) {
+ super(javaIdentifier, builder);
+ this.dyeColor = dyeColor;
+ }
+
+ public int dyeColor() {
+ return dyeColor;
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BedBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BedBlock.java
new file mode 100644
index 000000000..e72dbdafa
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BedBlock.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+public class BedBlock extends Block {
+ private final int dyeColor;
+
+ public BedBlock(String javaIdentifier, int dyeColor, Builder builder) {
+ super(javaIdentifier, builder);
+ this.dyeColor = dyeColor;
+ }
+
+ public int dyeColor() {
+ return dyeColor;
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java
new file mode 100644
index 000000000..ee99b652a
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.ints.IntList;
+import net.kyori.adventure.key.Key;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
+import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
+import org.geysermc.geyser.item.type.Item;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.BasicEnumProperty;
+import org.geysermc.geyser.level.block.property.IntegerProperty;
+import org.geysermc.geyser.level.block.property.Property;
+import org.geysermc.geyser.level.physics.PistonBehavior;
+import org.geysermc.geyser.registry.BlockRegistries;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
+import org.intellij.lang.annotations.Subst;
+
+import java.util.*;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+public class Block {
+ public static final int JAVA_AIR_ID = 0;
+
+ private final Key javaIdentifier;
+ /**
+ * Can you harvest this with your hand.
+ */
+ private final boolean requiresCorrectToolForDrops;
+ private final boolean hasBlockEntity;
+ private final float destroyTime;
+ private final @NonNull PistonBehavior pushReaction;
+ /**
+ * Used for classes we don't have implemented yet that override Mojmap getCloneItemStack with their own item.
+ * A supplier prevents any issues arising where the Items class finishes before the Blocks class.
+ */
+ private final Supplier- pickItem;
+ protected Item item = null;
+ private int javaId = -1;
+
+ /**
+ * Used for switching a given block state to different states.
+ */
+ private final Property>[] propertyKeys;
+ private final BlockState defaultState;
+
+ public Block(@Subst("empty") String javaIdentifier, Builder builder) {
+ this.javaIdentifier = Key.key(javaIdentifier);
+ this.requiresCorrectToolForDrops = builder.requiresCorrectToolForDrops;
+ this.hasBlockEntity = builder.hasBlockEntity;
+ this.destroyTime = builder.destroyTime;
+ this.pushReaction = builder.pushReaction;
+ this.pickItem = builder.pickItem;
+
+ BlockState firstState = builder.build(this).get(0);
+ this.propertyKeys = builder.propertyKeys; // Ensure this is not null before iterating over states
+ this.defaultState = setDefaultState(firstState);
+ }
+
+ public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
+ checkForEmptySkull(session, state, position);
+
+ BlockDefinition definition = session.getBlockMappings().getBedrockBlock(state);
+ sendBlockUpdatePacket(session, state, definition, position);
+
+ // Extended collision boxes for custom blocks
+ if (!session.getBlockMappings().getExtendedCollisionBoxes().isEmpty()) {
+ int aboveBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() + 1, position.getZ());
+ BlockDefinition aboveBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(state.javaId());
+ int belowBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() - 1, position.getZ());
+ BlockDefinition belowBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(belowBlock);
+ if (belowBedrockExtendedCollisionDefinition != null && state.is(Blocks.AIR)) {
+ UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
+ updateBlockPacket.setDataLayer(0);
+ updateBlockPacket.setBlockPosition(position);
+ updateBlockPacket.setDefinition(belowBedrockExtendedCollisionDefinition);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
+ session.sendUpstreamPacket(updateBlockPacket);
+ } else if (aboveBedrockExtendedCollisionDefinition != null && aboveBlock == Block.JAVA_AIR_ID) {
+ UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
+ updateBlockPacket.setDataLayer(0);
+ updateBlockPacket.setBlockPosition(position.add(0, 1, 0));
+ updateBlockPacket.setDefinition(aboveBedrockExtendedCollisionDefinition);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
+ session.sendUpstreamPacket(updateBlockPacket);
+ } else if (aboveBlock == Block.JAVA_AIR_ID) {
+ UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
+ updateBlockPacket.setDataLayer(0);
+ updateBlockPacket.setBlockPosition(position.add(0, 1, 0));
+ updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir());
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
+ session.sendUpstreamPacket(updateBlockPacket);
+ }
+ }
+ }
+
+ protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) {
+ UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
+ updateBlockPacket.setDataLayer(0);
+ updateBlockPacket.setBlockPosition(position);
+ updateBlockPacket.setDefinition(definition);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
+ session.sendUpstreamPacket(updateBlockPacket);
+
+ UpdateBlockPacket waterPacket = new UpdateBlockPacket();
+ waterPacket.setDataLayer(1);
+ waterPacket.setBlockPosition(position);
+ if (BlockRegistries.WATERLOGGED.get().get(state.javaId())) {
+ waterPacket.setDefinition(session.getBlockMappings().getBedrockWater());
+ } else {
+ waterPacket.setDefinition(session.getBlockMappings().getBedrockAir());
+ }
+ session.sendUpstreamPacket(waterPacket);
+ }
+
+ protected void checkForEmptySkull(GeyserSession session, BlockState state, Vector3i position) {
+ if (!(state.block() instanceof SkullBlock)) {
+ // Skull is gone
+ session.getSkullCache().removeSkull(position);
+ }
+ }
+
+ public Item asItem() {
+ if (this.item == null) {
+ return this.item = Item.byBlock(this);
+ }
+ return this.item;
+ }
+
+ public ItemStack pickItem(BlockState state) {
+ if (this.pickItem != null) {
+ return new ItemStack(this.pickItem.get().javaId());
+ }
+ return new ItemStack(this.asItem().javaId());
+ }
+
+ /**
+ * Should only be ran on block creation. Can be overridden.
+ * @param firstState the first state created from this block
+ */
+ protected BlockState setDefaultState(BlockState firstState) {
+ return firstState;
+ }
+
+ @NonNull
+ public Key javaIdentifier() {
+ return javaIdentifier;
+ }
+
+ public boolean requiresCorrectToolForDrops() {
+ return requiresCorrectToolForDrops;
+ }
+
+ public boolean hasBlockEntity() {
+ return hasBlockEntity;
+ }
+
+ public float destroyTime() {
+ return destroyTime;
+ }
+
+ @NonNull
+ public PistonBehavior pushReaction() {
+ return this.pushReaction;
+ }
+
+ public BlockState defaultBlockState() {
+ return this.defaultState;
+ }
+
+ public int javaId() {
+ return javaId;
+ }
+
+ public void setJavaId(int javaId) {
+ if (this.javaId != -1) {
+ throw new RuntimeException("Block ID has already been set!");
+ }
+ this.javaId = javaId;
+ }
+
+ @Override
+ public String toString() {
+ return "Block{" +
+ "javaIdentifier='" + javaIdentifier + '\'' +
+ ", javaId=" + javaId +
+ '}';
+ }
+
+ Property>[] propertyKeys() {
+ return propertyKeys;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private final Map, List>> states = new LinkedHashMap<>();
+ private boolean requiresCorrectToolForDrops = false;
+ private boolean hasBlockEntity = false;
+ private PistonBehavior pushReaction = PistonBehavior.NORMAL;
+ private float destroyTime;
+ private Supplier
- pickItem;
+
+ // We'll use this field after building
+ private Property>[] propertyKeys;
+
+ /**
+ * For states that we're just tracking for mirroring Java states.
+ */
+ public Builder enumState(BasicEnumProperty property) {
+ states.put(property, property.values());
+ return this;
+ }
+
+ @SafeVarargs
+ public final > Builder enumState(Property property, T... enums) {
+ states.put(property, List.of(enums));
+ return this;
+ }
+
+ public Builder booleanState(Property property) {
+ states.put(property, List.of(Boolean.TRUE, Boolean.FALSE)); // Make this list a static constant if it'll survive past initialization
+ return this;
+ }
+
+ public Builder intState(IntegerProperty property) {
+ int low = property.low();
+ int high = property.high();
+ IntList list = new IntArrayList();
+ // There is a state for every number between the low and high.
+ for (int i = low; i <= high; i++) {
+ list.add(i);
+ }
+ states.put(property, List.copyOf(list)); // Boxing reasons for that copy I guess.
+ return this;
+ }
+
+ public Builder requiresCorrectToolForDrops() {
+ this.requiresCorrectToolForDrops = true;
+ return this;
+ }
+
+ public Builder setBlockEntity() {
+ this.hasBlockEntity = true;
+ return this;
+ }
+
+ public Builder destroyTime(float destroyTime) {
+ this.destroyTime = destroyTime;
+ return this;
+ }
+
+ public Builder pushReaction(PistonBehavior pushReaction) {
+ this.pushReaction = pushReaction;
+ return this;
+ }
+
+ public Builder pickItem(Supplier
- pickItem) {
+ this.pickItem = pickItem;
+ return this;
+ }
+
+ private List build(Block block) {
+ if (states.isEmpty()) {
+ BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size());
+ BlockRegistries.BLOCK_STATES.get().add(state);
+ propertyKeys = null;
+ return List.of(state);
+ } else if (states.size() == 1) {
+ // We can optimize because we don't need to worry about combinations
+ Map.Entry, List>> property = this.states.entrySet().stream().findFirst().orElseThrow();
+ List states = new ArrayList<>(property.getValue().size());
+ property.getValue().forEach(value -> {
+ BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), new Comparable[] {value});
+ BlockRegistries.BLOCK_STATES.get().add(state);
+ states.add(state);
+ });
+ this.propertyKeys = new Property[]{property.getKey()};
+ return states;
+ } else {
+ // Think of this stream as another list containing, at the start, one empty list.
+ // It's two collections. Not a stream from the empty list.
+ Stream
>> stream = Stream.of(Collections.emptyList());
+ for (var values : this.states.values()) {
+ // OK, so here's how I understand this works. Because this was staring at vanilla Java code trying
+ // to figure out exactly how it works so we don't have any discrepencies.
+ // For each existing pair in the list, a new list is created, adding one of the new values.
+ // Property up [true/false] would exist as true and false
+ // Both entries will get duplicated, adding down, true and false.
+ stream = stream.flatMap(aPreviousPropertiesList ->
+ // So the above is a list. It may be empty if this is the first property,
+ // or it may be populated if this is not the first property.
+ // We're about to create a new stream, each with a new list,
+ // for every previous property
+ values.stream().map(value -> {
+ var newProperties = new ArrayList<>(aPreviousPropertiesList);
+ newProperties.add(value);
+ return newProperties;
+ }));
+ }
+
+ List states = new ArrayList<>();
+ // Now we have a list of Pairs. Each list is a block state!
+ // If we have two boolean properties: up [true/false] and down [true/false],
+ // We'll see [up=true,down=true], [up=false,down=true], [up=true,down=false], [up=false,down=false]
+ List>> result = stream.toList();
+ // Ensure each block state shares the same key array. Creating a keySet here shouldn't be an issue since
+ // this states map should be removed after build.
+ Property>[] keys = this.states.keySet().toArray(new Property>[0]);
+ result.forEach(properties -> {
+ Comparable>[] values = properties.toArray(new Comparable>[0]);
+ BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), values);
+ BlockRegistries.BLOCK_STATES.get().add(state);
+ states.add(state);
+ });
+ this.propertyKeys = keys;
+ return states;
+ }
+ }
+
+ private Builder() {
+ }
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java
new file mode 100644
index 000000000..36c31f32e
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.geysermc.geyser.level.block.property.Property;
+import org.geysermc.geyser.registry.BlockRegistries;
+
+import java.util.Locale;
+
+public final class BlockState {
+ private final Block block;
+ private final int javaId;
+ /**
+ * The values of each property of this block state. These should be treated as keys to {@link Block#propertyKeys()}.
+ * Of note - the comparable part probably doesn't do anything because we occasionally use strings in place of enums.
+ * Will be null if there's only one block state for a block.
+ */
+ private final Comparable>[] states;
+
+ public BlockState(Block block, int javaId) {
+ this(block, javaId, null);
+ }
+
+ BlockState(Block block, int javaId, Comparable>[] states) {
+ this.block = block;
+ this.javaId = javaId;
+ this.states = states;
+ }
+
+ public > T getValue(Property property) {
+ //noinspection unchecked
+ return (T) get(property);
+ }
+
+ public > T getValueNullable(Property property) {
+ var value = get(property);
+ if (value == null) {
+ return null;
+ }
+ //noinspection unchecked
+ return (T) get(property);
+ }
+
+ public boolean getValue(Property property, boolean def) {
+ var value = get(property);
+ if (value == null) {
+ return def;
+ }
+ return (Boolean) value;
+ }
+
+ @Nullable
+ private Comparable> get(Property> property) {
+ Property>[] keys = this.block.propertyKeys();
+ if (keys == null) {
+ return null;
+ }
+ // We're copying the behavior Reference2ObjectArrayMap uses
+ for (int i = keys.length; i-- != 0;) {
+ if (keys[i] == property) {
+ return this.states[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return the {@link BlockState} instance with the given value.
+ */
+ public > BlockState withValue(Property property, T value) {
+ Property>[] keys = this.block.propertyKeys();
+ if (keys == null) {
+ throw new IllegalStateException(this + " does not have any different states!");
+ }
+
+ T currentValue = getValue(property);
+ if (currentValue == null) {
+ throw new IllegalArgumentException("This BlockState does not have the property " + property);
+ }
+ if (currentValue.equals(value)) {
+ // No action required. This block state is the state we're looking for.
+ return this;
+ }
+
+ // Diff is how much we will have to traverse as a sort of offset
+
+ // Block states are calculated in a predictable structure:
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=none]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=low]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=tall]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=none]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=low]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=tall]
+ // minecraft:cobblestone_wall[east=none,north=none,south=none,up=false,waterlogged=true,west=none]
+
+ // The last value goes through all its iterations, then the next state goes through all its iterations.
+ // West goes none -> low -> tall, then waterlogged is toggled as west cycles again.
+ // Then when waterlogged goes through all its properties, up is toggled, and west goes through again
+ // If we want to find the "up" property in order, then we need to find how many iterations each property
+ // after it goes in. West goes for 3, waterlogged goes for 2. Adding those together, we find that we need to
+ // add five to get to the next toggle of the up property
+ int diff = 0;
+ for (int i = keys.length - 1; i >= 0; i--) {
+ if (keys[i] != property) {
+ diff += keys[i].valuesCount();
+ } else {
+ break;
+ }
+ }
+
+ // How many times do we have to jump by diff? This depends on how far away each value is from each other.
+ // piston_head[facing=north] might be right next to piston_head[facing=south], which just one diff'd hop.
+ // But piston_head[facing=west] is further away, requiring more hops.
+ int thatOffset = property.indexOf(value);
+ int thisOffset = property.indexOf(currentValue);
+ if (diff == 0) {
+ // This can happen if the property is at the tail end of the block and there are no other properties to look through
+ // If we have minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=none]
+ // And want minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=low]
+ // The above for loop will always stop at the first break because the last property has already been found
+ diff = 1;
+ }
+ return of(this.javaId + ((thatOffset - thisOffset) * diff));
+ }
+
+ public Block block() {
+ return this.block;
+ }
+
+ public int javaId() {
+ return this.javaId;
+ }
+
+ public boolean is(Block block) {
+ return this.block == block;
+ }
+
+ @Override
+ public String toString() {
+ if (this.states == null) {
+ return this.block.javaIdentifier().toString();
+ }
+ return this.block.javaIdentifier().toString() + "[" + paramsToString() + "]";
+ }
+
+ private String paramsToString() {
+ StringBuilder builder = new StringBuilder();
+ Property>[] propertyKeys = this.block.propertyKeys();
+ if (propertyKeys != null) {
+ for (int i = 0; i < propertyKeys.length; i++) {
+ builder.append(propertyKeys[i].name())
+ .append("=")
+ .append(this.states[i].toString().toLowerCase(Locale.ROOT)); // lowercase covers enums
+ if (i < propertyKeys.length - 1) {
+ builder.append(",");
+ }
+ }
+ }
+ return builder.toString();
+ }
+
+ public static BlockState of(int javaId) {
+ return BlockRegistries.BLOCK_STATES.get(javaId);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/CauldronBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/CauldronBlock.java
new file mode 100644
index 000000000..d27969af7
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/CauldronBlock.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.nbt.NbtList;
+import org.cloudburstmc.nbt.NbtMap;
+import org.cloudburstmc.nbt.NbtType;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag;
+import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
+
+public class CauldronBlock extends Block implements BedrockChunkWantsBlockEntityTag {
+ public CauldronBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) {
+ // As of 1.18.30: this is required to make rendering not look weird on chunk load (lava and snow cauldrons look dim)
+ return BlockEntityTranslator.getConstantBedrockTag("Cauldron", position.getX(), position.getY(), position.getZ())
+ .putByte("isMovable", (byte) 0)
+ .putShort("PotionId", (short) -1)
+ .putShort("PotionType", (short) -1)
+ .putList("Items", NbtType.END, NbtList.EMPTY)
+ .build();
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/ChestBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/ChestBlock.java
new file mode 100644
index 000000000..69132ccfd
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/ChestBlock.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.geysermc.geyser.level.block.property.ChestType;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
+import org.geysermc.geyser.util.BlockEntityUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
+
+public class ChestBlock extends Block {
+ public ChestBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
+ super.updateBlock(session, state, position);
+
+ if (state.getValue(Properties.CHEST_TYPE) != ChestType.SINGLE) {
+ NbtMapBuilder tagBuilder = BlockEntityTranslator.getConstantBedrockTag(BlockEntityType.CHEST, position.getX(), position.getY(), position.getZ());
+ BlockEntityUtils.getBlockEntityTranslator(BlockEntityType.CHEST).translateTag(session, tagBuilder, null, state); //TODO
+ BlockEntityUtils.updateBlockEntity(session, tagBuilder.build(), position);
+ }
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java
new file mode 100644
index 000000000..bfde51a79
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.util.ChunkUtils;
+
+public class DoorBlock extends Block {
+ public DoorBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
+ super.updateBlock(session, state, position);
+
+ if (state.getValue(Properties.DOUBLE_BLOCK_HALF).equals("upper")) {
+ // Update the lower door block as Bedrock client doesn't like door to be closed from the top
+ // See https://github.com/GeyserMC/Geyser/issues/4358
+ Vector3i belowDoorPosition = position.sub(0, 1, 0);
+ BlockState belowDoorBlockState = session.getGeyser().getWorldManager().blockAt(session, belowDoorPosition.getX(), belowDoorPosition.getY(), belowDoorPosition.getZ());
+ ChunkUtils.updateBlock(session, belowDoorBlockState, belowDoorPosition);
+ }
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java
similarity index 60%
rename from core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java
rename to core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java
index 074fff6ef..5107616af 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,64 +23,36 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.geyser.translator.level.block.entity;
+package org.geysermc.geyser.level.block.type;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag;
+import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
import org.geysermc.geyser.util.BlockEntityUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
-public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity {
- /**
- * @param blockState the Java block state of a potential flower pot block
- * @return true if the block is a flower pot
- */
- public static boolean isFlowerBlock(int blockState) {
- return BlockStateValues.getFlowerPotValues().containsKey(blockState);
- }
+public class FlowerPotBlock extends Block implements BedrockChunkWantsBlockEntityTag {
+ private final Block flower;
- /**
- * Get the Nukkit CompoundTag of the flower pot.
- *
- * @param blockState Java block state of flower pot.
- * @param position Bedrock position of flower pot.
- * @return Bedrock tag of flower pot.
- */
- public static NbtMap getTag(GeyserSession session, int blockState, Vector3i position) {
- NbtMapBuilder tagBuilder = NbtMap.builder()
- .putInt("x", position.getX())
- .putInt("y", position.getY())
- .putInt("z", position.getZ())
- .putByte("isMovable", (byte) 1)
- .putString("id", "FlowerPot");
- // Get the Java name of the plant inside. e.g. minecraft:oak_sapling
- String name = BlockStateValues.getFlowerPotValues().get(blockState);
- if (name != null) {
- // Get the Bedrock CompoundTag of the block.
- // This is where we need to store the *Java* name because Bedrock has six minecraft:sapling blocks with different block states.
- NbtMap plant = session.getBlockMappings().getFlowerPotBlocks().get(name);
- if (plant != null) {
- tagBuilder.put("PlantBlock", plant.toBuilder().build());
- }
- }
- return tagBuilder.build();
+ public FlowerPotBlock(String javaIdentifier, Block flower, Builder builder) {
+ super(javaIdentifier, builder);
+ this.flower = flower;
}
@Override
- public boolean isBlock(int blockState) {
- return isFlowerBlock(blockState);
- }
+ public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
+ super.updateBlock(session, state, position);
- @Override
- public void updateBlock(GeyserSession session, int blockState, Vector3i position) {
- NbtMap tag = getTag(session, blockState, position);
+ NbtMap tag = createTag(session, position, state);
BlockEntityUtils.updateBlockEntity(session, tag, position);
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
updateBlockPacket.setDataLayer(0);
- updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(blockState));
+ updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(state));
updateBlockPacket.setBlockPosition(position);
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
@@ -88,4 +60,33 @@ public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity {
session.sendUpstreamPacket(updateBlockPacket);
BlockEntityUtils.updateBlockEntity(session, tag, position);
}
+
+ @Override
+ public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) {
+ NbtMapBuilder tagBuilder = BlockEntityTranslator.getConstantBedrockTag("FlowerPot", position.getX(), position.getY(), position.getZ())
+ .putByte("isMovable", (byte) 1);
+ // Get the Java name of the plant inside. e.g. minecraft:oak_sapling
+ if (this.flower != Blocks.AIR) {
+ // Get the Bedrock CompoundTag of the block.
+ // This is where we need to store the *Java* name because Bedrock has six minecraft:sapling blocks with different block states.
+ // TODO flattening might make this nicer in the future!
+ NbtMap plant = session.getBlockMappings().getFlowerPotBlocks().get(this.flower);
+ if (plant != null) {
+ tagBuilder.putCompound("PlantBlock", plant.toBuilder().build());
+ }
+ }
+ return tagBuilder.build();
+ }
+
+ @Override
+ public ItemStack pickItem(BlockState state) {
+ if (this.flower != Blocks.AIR) {
+ return new ItemStack(this.flower.asItem().javaId());
+ }
+ return super.pickItem(state);
+ }
+
+ public Block flower() {
+ return flower;
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java
new file mode 100644
index 000000000..25d54ff2d
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.physics.Direction;
+
+public class FurnaceBlock extends Block {
+ public FurnaceBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ protected BlockState setDefaultState(BlockState firstState) {
+ // Both furnace minecart states look north.
+ return firstState.withValue(Properties.HORIZONTAL_FACING, Direction.NORTH);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java
new file mode 100644
index 000000000..642240915
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+public class HoneyBlock extends Block {
+ public HoneyBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java
new file mode 100644
index 000000000..3139bd6de
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.nbt.NbtMap;
+import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.cloudburstmc.nbt.NbtType;
+import org.geysermc.geyser.level.WorldManager;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag;
+import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
+import org.geysermc.geyser.util.BlockEntityUtils;
+
+import java.util.Collections;
+
+public class LecternBlock extends Block implements BedrockChunkWantsBlockEntityTag {
+ public LecternBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) {
+ return getBaseLecternTag(position, blockState.getValue(Properties.HAS_BOOK));
+ }
+
+ @Override
+ public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
+ WorldManager worldManager = session.getGeyser().getWorldManager();
+ boolean currentHasBook = state.getValue(Properties.HAS_BOOK);
+ Boolean previousHasBook = worldManager.blockAt(session, position).getValueNullable(Properties.HAS_BOOK); // Can be null if not a lectern, watch out
+ if (previousHasBook == null || currentHasBook != previousHasBook) {
+ BlockEntityUtils.updateBlockEntity(session, getBaseLecternTag(position, currentHasBook), position);
+ }
+ super.updateBlock(session, state, position);
+ }
+
+ public static NbtMap getBaseLecternTag(Vector3i position, boolean hasBook) {
+ if (hasBook) {
+ return getBaseLecternTag(position, 1)
+ .putCompound("book", NbtMap.builder()
+ .putByte("Count", (byte) 1)
+ .putShort("Damage", (short) 0)
+ .putString("Name", "minecraft:writable_book")
+ .putCompound("tag", NbtMap.builder().putList("pages", NbtType.COMPOUND, Collections.singletonList(
+ NbtMap.builder()
+ .putString("photoname", "")
+ .putString("text", "")
+ .build()
+ )).build())
+ .build())
+ .build();
+ } else {
+ return getBaseLecternTag(position, 0).build();
+ }
+ }
+
+ public static NbtMapBuilder getBaseLecternTag(Vector3i position, int pages) {
+ NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("Lectern", position);
+ builder.putBoolean("isMovable", true);
+
+ if (pages != 0) {
+ builder.putByte("hasBook", (byte) 1);
+ builder.putInt("totalPages", 1); // we'll override it anyway
+ }
+
+ return builder;
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/MovingPistonBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/MovingPistonBlock.java
new file mode 100644
index 000000000..e4df8d88b
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/MovingPistonBlock.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
+import org.geysermc.geyser.session.GeyserSession;
+
+public class MovingPistonBlock extends Block {
+ public MovingPistonBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) {
+ // Prevent moving_piston from being placed
+ // It's used for extending piston heads, but it isn't needed on Bedrock and causes pistons to flicker
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/PistonBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonBlock.java
new file mode 100644
index 000000000..fc54115eb
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonBlock.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.nbt.NbtMap;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag;
+import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity;
+
+public class PistonBlock extends Block implements BedrockChunkWantsBlockEntityTag {
+ public PistonBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) {
+ boolean extended = blockState.getValue(Properties.EXTENDED);
+ boolean sticky = blockState.is(Blocks.STICKY_PISTON);
+ return PistonBlockEntity.buildStaticPistonTag(position, extended, sticky);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/PistonHeadBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonHeadBlock.java
new file mode 100644
index 000000000..8a6b4f41c
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonHeadBlock.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
+
+public class PistonHeadBlock extends Block {
+ public PistonHeadBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+
+ @Override
+ public ItemStack pickItem(BlockState state) {
+ Block block = state.getValue(Properties.PISTON_TYPE).equals("sticky") ? Blocks.STICKY_PISTON : Blocks.PISTON;
+ return new ItemStack(block.asItem().javaId());
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java
new file mode 100644
index 000000000..c4aae46a2
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import com.github.steveice10.mc.auth.data.GameProfile;
+import org.cloudburstmc.math.vector.Vector3i;
+import org.cloudburstmc.nbt.NbtMap;
+import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
+import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.session.cache.SkullCache;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
+
+import java.util.Collections;
+import java.util.UUID;
+
+public class SkullBlock extends Block {
+ private final Type type;
+
+ public SkullBlock(String javaIdentifier, Type type, Builder builder) {
+ super(javaIdentifier, builder);
+ this.type = type;
+ }
+
+ @Override
+ protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) {
+ if (this.type == Type.PLAYER) {
+ // The changed block was a player skull so check if a custom block was defined for this skull
+ SkullCache.Skull skull = session.getSkullCache().updateSkull(position, state);
+ if (skull != null && skull.getBlockDefinition() != null) {
+ definition = skull.getBlockDefinition();
+ }
+ }
+ super.sendBlockUpdatePacket(session, state, definition, position);
+ }
+
+ @Override
+ protected void checkForEmptySkull(GeyserSession session, BlockState state, Vector3i position) {
+ // It's not an empty skull.
+ }
+
+ public ItemStack pickItem(GeyserSession session, BlockState state, Vector3i position) {
+ SkullCache.Skull skull = session.getSkullCache().getSkulls().get(position);
+ if (skull == null) {
+ return new ItemStack(pickItem(state).getId());
+ }
+
+ GeyserItemStack itemStack = GeyserItemStack.of(pickItem(state).getId(), 1);
+ // This is a universal block entity behavior, but hardcode how it works for now.
+ NbtMapBuilder builder = NbtMap.builder()
+ .putString("id", "minecraft:skull")
+ .putInt("x", position.getX())
+ .putInt("y", position.getY())
+ .putInt("z", position.getZ());
+ DataComponents components = itemStack.getOrCreateComponents();
+ components.put(DataComponentType.BLOCK_ENTITY_DATA, builder.build());
+
+ UUID uuid = skull.getUuid();
+ String texturesProperty = skull.getTexturesProperty();
+ GameProfile profile = new GameProfile(uuid, null);
+ if (texturesProperty != null) {
+ profile.setProperties(Collections.singletonList(new GameProfile.Property("textures", texturesProperty)));
+ }
+ components.put(DataComponentType.PROFILE, profile);
+ return itemStack.getItemStack();
+ }
+
+ public Type skullType() {
+ return type;
+ }
+
+ /**
+ * Enum order matches Java.
+ */
+ public enum Type {
+ SKELETON(0),
+ WITHER_SKELETON(1),
+ PLAYER(3),
+ ZOMBIE(2),
+ CREEPER(4),
+ PIGLIN(6),
+ DRAGON(5);
+
+ private final int bedrockId;
+
+ Type(int bedrockId) {
+ this.bedrockId = bedrockId;
+ }
+
+ public int bedrockId() {
+ return bedrockId;
+ }
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java
new file mode 100644
index 000000000..968499d11
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+public class SpawnerBlock extends Block {
+ public SpawnerBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/TrapDoorBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/TrapDoorBlock.java
new file mode 100644
index 000000000..a94414ac2
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/TrapDoorBlock.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+public class TrapDoorBlock extends Block {
+ public TrapDoorBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/WallSkullBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/WallSkullBlock.java
new file mode 100644
index 000000000..e8fedcc76
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/WallSkullBlock.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.physics.Direction;
+
+public class WallSkullBlock extends SkullBlock {
+ public WallSkullBlock(String javaIdentifier, Type type, Builder builder) {
+ super(javaIdentifier, type, builder);
+ }
+
+ public static int getDegrees(BlockState state) {
+ return getDegrees(state.getValue(Properties.HORIZONTAL_FACING));
+ }
+
+ public static int getDegrees(Direction direction) {
+ return switch (direction) {
+ case NORTH -> 180;
+ case WEST -> 90;
+ case EAST -> 270;
+ case SOUTH -> 0;
+ default -> throw new IllegalStateException();
+ };
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java
new file mode 100644
index 000000000..9d2d23116
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.level.block.type;
+
+public class WaterBlock extends Block {
+ public WaterBlock(String javaIdentifier, Builder builder) {
+ super(javaIdentifier, builder);
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
index ce89689eb..2be4e7a38 100644
--- a/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
+++ b/core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java
@@ -39,6 +39,9 @@ import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.PistonCache;
import org.geysermc.geyser.translator.collision.BlockCollision;
@@ -405,7 +408,8 @@ public class CollisionManager {
* @return if the player is currently in a water block
*/
public boolean isPlayerInWater() {
- return session.getGeyser().getWorldManager().getBlockAt(session, session.getPlayerEntity().getPosition().toInt()) == BlockStateValues.JAVA_WATER_ID;
+ BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getPlayerEntity().getPosition().toInt());
+ return state.is(Blocks.WATER) && state.getValue(Properties.LEVEL) == 0;
}
public boolean isWaterInEyes() {
diff --git a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java
index 6bd767fb7..e7cf81d47 100644
--- a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java
+++ b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java
@@ -224,7 +224,7 @@ class CodecProcessor {
@SuppressWarnings("unchecked")
static BedrockCodec processCodec(BedrockCodec codec) {
- return codec.toBuilder()
+ BedrockCodec.Builder codecBuilder = codec.toBuilder()
// Illegal unused serverbound EDU packets
.updateSerializer(PhotoTransferPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(LabTablePacket.class, ILLEGAL_SERIALIZER)
@@ -232,10 +232,11 @@ class CodecProcessor {
.updateSerializer(CreatePhotoPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(NpcRequestPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(PhotoInfoRequestPacket.class, ILLEGAL_SERIALIZER)
- // Illegal unused serverbound packets for featured servers
- .updateSerializer(PurchaseReceiptPacket.class, ILLEGAL_SERIALIZER)
+ // Unused serverbound packets for featured servers, which is for some reason still occasionally sent
+ .updateSerializer(PurchaseReceiptPacket.class, IGNORED_SERIALIZER)
// Illegal unused serverbound packets that are deprecated
.updateSerializer(ClientCheatAbilityPacket.class, ILLEGAL_SERIALIZER)
+ .updateSerializer(CraftingEventPacket.class, ILLEGAL_SERIALIZER)
// Illegal unusued serverbound packets that relate to unused features
.updateSerializer(PlayerAuthInputPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(ClientCacheBlobStatusPacket.class, ILLEGAL_SERIALIZER)
@@ -243,7 +244,6 @@ class CodecProcessor {
.updateSerializer(SubChunkRequestPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(GameTestRequestPacket.class, ILLEGAL_SERIALIZER)
// Ignored serverbound packets
- .updateSerializer(CraftingEventPacket.class, IGNORED_SERIALIZER) // Make illegal when 1.20.40 is removed
.updateSerializer(ClientToServerHandshakePacket.class, IGNORED_SERIALIZER)
.updateSerializer(EntityFallPacket.class, IGNORED_SERIALIZER)
.updateSerializer(MapCreateLockedCopyPacket.class, IGNORED_SERIALIZER)
@@ -260,22 +260,25 @@ class CodecProcessor {
.updateSerializer(PlayerHotbarPacket.class, PLAYER_HOTBAR_SERIALIZER)
.updateSerializer(PlayerSkinPacket.class, PLAYER_SKIN_SERIALIZER)
.updateSerializer(SetEntityDataPacket.class, SET_ENTITY_DATA_SERIALIZER)
- .updateSerializer(SetEntityMotionPacket.class, codec.getProtocolVersion() < 662 ?
- SET_ENTITY_MOTION_SERIALIZER_V291 :
- SET_ENTITY_MOTION_SERIALIZER_V662)
+ .updateSerializer(SetEntityMotionPacket.class, SET_ENTITY_MOTION_SERIALIZER_V662)
.updateSerializer(SetEntityLinkPacket.class, SET_ENTITY_LINK_SERIALIZER)
// Valid serverbound packets where reading of some fields can be skipped
.updateSerializer(MobEquipmentPacket.class, MOB_EQUIPMENT_SERIALIZER)
- // // Illegal bidirectional packets
+ // Illegal bidirectional packets
.updateSerializer(DebugInfoPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(EditorNetworkPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(ScriptMessagePacket.class, ILLEGAL_SERIALIZER)
- // // Ignored bidirectional packets
+ // Ignored bidirectional packets
.updateSerializer(ClientCacheStatusPacket.class, IGNORED_SERIALIZER)
.updateSerializer(SimpleEventPacket.class, IGNORED_SERIALIZER)
- .updateSerializer(TickSyncPacket.class, IGNORED_SERIALIZER)
- .updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER)
- .build();
+ .updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER);
+
+ if (codec.getProtocolVersion() < 685) {
+ // Ignored bidirectional packets
+ codecBuilder.updateSerializer(TickSyncPacket.class, IGNORED_SERIALIZER);
+ }
+
+ return codecBuilder.build();
}
/**
diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java
index f9292671f..1c58288c7 100644
--- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java
+++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java
@@ -27,11 +27,8 @@ package org.geysermc.geyser.network;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
-import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622;
-import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630;
-import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649;
-import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662;
import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671;
+import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685;
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec;
@@ -50,8 +47,8 @@ public final class GameProtocol {
* Default Bedrock codec that should act as a fallback. Should represent the latest available
* release of the game that Geyser supports.
*/
- public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v671.CODEC.toBuilder()
- .minecraftVersion("1.20.81")
+ public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v685.CODEC.toBuilder()
+ .minecraftVersion("1.21.0")
.build());
/**
@@ -66,20 +63,11 @@ public final class GameProtocol {
private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC;
static {
- SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v622.CODEC.toBuilder()
- .minecraftVersion("1.20.40/1.20.41")
- .build()));
- SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v630.CODEC.toBuilder()
- .minecraftVersion("1.20.50/1.20.51")
- .build()));
- SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v649.CODEC.toBuilder()
- .minecraftVersion("1.20.60/1.20.62")
- .build()));
- SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v662.CODEC.toBuilder()
- .minecraftVersion("1.20.70/1.20.73")
+ SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v671.CODEC.toBuilder()
+ .minecraftVersion("1.20.80/1.20.81")
.build()));
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(DEFAULT_BEDROCK_CODEC.toBuilder()
- .minecraftVersion("1.20.80/1.20.81")
+ .minecraftVersion("1.21.0")
.build()));
}
@@ -99,16 +87,8 @@ public final class GameProtocol {
/* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */
- public static boolean isPre1_20_50(GeyserSession session) {
- return session.getUpstream().getProtocolVersion() < Bedrock_v630.CODEC.getProtocolVersion();
- }
-
- public static boolean isPre1_20_70(GeyserSession session) {
- return session.getUpstream().getProtocolVersion() < Bedrock_v662.CODEC.getProtocolVersion();
- }
-
- public static boolean is1_20_60orHigher(int protocolVersion) {
- return protocolVersion >= Bedrock_v649.CODEC.getProtocolVersion();
+ public static boolean isPre1_21_0(GeyserSession session) {
+ return session.getUpstream().getProtocolVersion() < Bedrock_v685.CODEC.getProtocolVersion();
}
/**
diff --git a/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java
index 3e836711b..1b653891e 100644
--- a/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java
+++ b/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java
@@ -47,7 +47,9 @@ public class InvalidPacketHandler extends ChannelInboundHandlerAdapter {
if (!(rootCause instanceof IllegalArgumentException)) {
- super.exceptionCaught(ctx, cause);
+ // Kick users that cause exceptions
+ session.getGeyser().getLogger().warning("Exception caught in session of" + session.bedrockUsername() + ": " + rootCause.getMessage());
+ session.disconnect("An internal error occurred!");
return;
}
diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java
index 23ab1697f..c7aabb806 100644
--- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java
+++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java
@@ -132,6 +132,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
}
session.getUpstream().getSession().setCodec(packetCodec);
+ // FIXME temporary until 1.20.80 is dropped
+ session.getPlayerEntity().resetAir();
return true;
}
diff --git a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
index 320334ee5..27b405348 100644
--- a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
+++ b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java
@@ -35,10 +35,7 @@ import org.cloudburstmc.nbt.util.VarInts;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.network.GameProtocol;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import java.io.*;
import java.net.*;
import java.util.concurrent.TimeUnit;
@@ -139,6 +136,9 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn
this.geyser.getLogger().debug("Connection timeout for ping passthrough.");
} catch (JsonParseException | JsonMappingException ex) {
this.geyser.getLogger().error("Failed to parse json when pinging server!", ex);
+ } catch (EOFException e) {
+ this.pingInfo = null;
+ this.geyser.getLogger().warning("Failed to ping the remote Java server! Is it online and configured in Geyser's config?");
} catch (UnknownHostException ex) {
// Don't reset pingInfo, as we want to keep the last known value
this.geyser.getLogger().warning("Unable to resolve remote host! Is the remote server down or invalid?");
diff --git a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java
index aa9d6fc36..2f15094ef 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java
@@ -34,18 +34,20 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.api.block.custom.CustomBlockState;
import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.registry.loader.CollisionRegistryLoader;
import org.geysermc.geyser.registry.loader.RegistryLoaders;
import org.geysermc.geyser.registry.populator.BlockRegistryPopulator;
import org.geysermc.geyser.registry.populator.CustomBlockRegistryPopulator;
import org.geysermc.geyser.registry.populator.CustomSkullRegistryPopulator;
-import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.registry.type.BlockMappings;
import org.geysermc.geyser.registry.type.CustomSkull;
import org.geysermc.geyser.translator.collision.BlockCollision;
+import java.util.ArrayList;
import java.util.BitSet;
-
import java.util.Set;
/**
@@ -59,34 +61,32 @@ public class BlockRegistries {
public static final VersionedRegistry BLOCKS = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new));
/**
- * A mapped registry which stores Java to Bedrock block identifiers.
+ * A registry which stores Java IDs to Java {@link BlockState}s, each with their specific state differences and a link
+ * to the overarching block.
*/
- public static final SimpleMappedRegistry JAVA_TO_BEDROCK_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
-
- /**
- * A registry which stores Java IDs to {@link BlockMapping}, containing miscellaneous information about
- * blocks and their behavior in many cases.
- */
- public static final ArrayRegistry JAVA_BLOCKS = ArrayRegistry.create(RegistryLoaders.uninitialized());
+ public static final ListRegistry BLOCK_STATES = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
/**
* A mapped registry containing which holds block IDs to its {@link BlockCollision}.
*/
- public static final IntMappedRegistry COLLISIONS;
+ public static final ListRegistry COLLISIONS;
+
+ /**
+ * A registry which stores Java IDs to {@link Block}, containing miscellaneous information about
+ * blocks and their behavior in many cases.
+ */
+ public static final ListRegistry JAVA_BLOCKS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
/**
* A mapped registry containing the Java identifiers to IDs.
*/
public static final MappedRegistry> JAVA_IDENTIFIER_TO_ID = MappedRegistry.create(RegistryLoaders.empty(Object2IntOpenHashMap::new));
- /**
- * A registry which stores unique Java IDs to its clean identifier
- * This is used in the statistics form.
- */
- public static final ArrayRegistry CLEAN_JAVA_IDENTIFIERS = ArrayRegistry.create(RegistryLoaders.uninitialized());
-
/**
* A registry containing all the waterlogged blockstates.
+ * Properties.WATERLOGGED should not be relied on for two reasons:
+ * - Custom blocks
+ * - Seagrass, kelp, and bubble columns are assumed waterlogged and don't have a waterlogged property
*/
public static final SimpleRegistry WATERLOGGED = SimpleRegistry.create(RegistryLoaders.empty(BitSet::new));
@@ -131,12 +131,13 @@ public class BlockRegistries {
public static final SimpleMappedRegistry CUSTOM_SKULLS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
static {
+ Blocks.VAULT.javaId(); // FIXME
CustomSkullRegistryPopulator.populate();
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.PRE_INIT);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.DEFINITION);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.NON_VANILLA_REGISTRATION);
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_JAVA);
- COLLISIONS = IntMappedRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collision.json"), CollisionRegistryLoader::new);
+ COLLISIONS = ListRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collisions.nbt"), CollisionRegistryLoader::new);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.VANILLA_REGISTRATION);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION);
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK);
diff --git a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java
new file mode 100644
index 000000000..2070d67ae
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.registry;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.geysermc.geyser.registry.loader.RegistryLoader;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Supplier;
+
+public class ListRegistry extends Registry> {
+ private boolean frozen = false;
+
+ /**
+ * Creates a new instance of this class with the given input and
+ * {@link RegistryLoader}. The input specified is what the registry
+ * loader needs to take in.
+ *
+ * @param input the input
+ * @param registryLoader the registry loader
+ */
+ protected ListRegistry(I input, RegistryLoader> registryLoader) {
+ super(input, registryLoader);
+ }
+
+ /**
+ * Returns the value registered by the given index.
+ *
+ * @param index the index
+ * @return the value registered by the given index.
+ */
+ @Nullable
+ public M get(int index) {
+ if (index >= this.mappings.size()) {
+ return null;
+ }
+
+ return this.mappings.get(index);
+ }
+
+ /**
+ * Returns the value registered by the given index or the default value
+ * specified if null.
+ *
+ * @param index the index
+ * @param defaultValue the default value
+ * @return the value registered by the given key or the default value
+ * specified if null.
+ */
+ public M getOrDefault(int index, M defaultValue) {
+ M value = this.get(index);
+ if (value == null) {
+ return defaultValue;
+ }
+
+ return value;
+ }
+
+ /**
+ * Registers a new value into this registry with the given index.
+ *
+ * @param index the index
+ * @param value the value
+ * @return a new value into this registry with the given index.
+ */
+ public M register(int index, M value) {
+ if (this.frozen) {
+ throw new IllegalStateException("Registry should not be modified after frozen!");
+ }
+ return this.mappings.set(index, value);
+ }
+
+ /**
+ * Registers a new value into this registry with the given index, even if this value would normally be outside
+ * the range of a list.
+ *
+ * @param index the index
+ * @param value the value
+ * @param defaultValue the default value to fill empty spaces in the registry with.
+ * @return a new value into this registry with the given index.
+ */
+ public M registerWithAnyIndex(int index, M value, M defaultValue) {
+ if (this.frozen) {
+ throw new IllegalStateException("Registry should not be modified after frozen!");
+ }
+ if (this.mappings.size() <= index) {
+ this.mappings.addAll(Collections.nCopies(index - this.mappings.size() + 1, defaultValue));
+ }
+ return this.mappings.set(index, value);
+ }
+
+ /**
+ * Mark this registry as unsuitable for new additions. The backing list will then be optimized for storage.
+ */
+ public void freeze() {
+ if (!this.frozen) {
+ this.frozen = true;
+ if (this.mappings instanceof ArrayList arrayList) {
+ arrayList.trimToSize();
+ }
+ }
+ }
+
+ /**
+ * Creates a new array registry with the given {@link RegistryLoader}. The
+ * input type is not specified here, meaning the loader return type is either
+ * predefined, or the registry is populated at a later point.
+ *
+ * @param registryLoader the registry loader
+ * @param the input type
+ * @param the returned mappings type
+ * @return a new registry with the given RegistryLoader supplier
+ */
+ public static ListRegistry create(RegistryLoader> registryLoader) {
+ return new ListRegistry<>(null, registryLoader);
+ }
+
+ /**
+ * Creates a new integer mapped registry with the given {@link RegistryLoader} and input.
+ *
+ * @param registryLoader the registry loader
+ * @param the input
+ * @param the type value
+ * @return a new registry with the given RegistryLoader supplier
+ */
+ public static ListRegistry create(I input, Supplier>> registryLoader) {
+ return new ListRegistry<>(input, registryLoader.get());
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java
index 54d013140..b509d6ac0 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java
@@ -127,7 +127,10 @@ public final class Registries {
*/
public static final PacketTranslatorRegistry JAVA_PACKET_TRANSLATORS = PacketTranslatorRegistry.create();
- public static final SimpleRegistry> JAVA_ITEMS = SimpleRegistry.create(RegistryLoaders.empty(ArrayList::new));
+ /**
+ * A registry containing all Java items ordered by their network ID.
+ */
+ public static final ListRegistry- JAVA_ITEMS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
public static final SimpleMappedRegistry JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java
index 95e8bd2c1..bd98ae0a5 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/loader/CollisionRegistryLoader.java
@@ -25,18 +25,19 @@
package org.geysermc.geyser.registry.loader;
-import com.fasterxml.jackson.databind.node.ArrayNode;
import it.unimi.dsi.fastutil.Pair;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import lombok.AllArgsConstructor;
import org.checkerframework.checker.nullness.qual.Nullable;
+import org.cloudburstmc.nbt.NbtList;
+import org.cloudburstmc.nbt.NbtMap;
+import org.cloudburstmc.nbt.NbtType;
+import org.cloudburstmc.nbt.NbtUtils;
import org.geysermc.geyser.GeyserImpl;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.translator.collision.BlockCollision;
import org.geysermc.geyser.translator.collision.CollisionRemapper;
import org.geysermc.geyser.translator.collision.OtherCollision;
@@ -51,41 +52,43 @@ import java.util.regex.Pattern;
/**
* Loads collision data from the given resource path.
*/
-public class CollisionRegistryLoader extends MultiResourceRegistryLoader> {
+public class CollisionRegistryLoader extends MultiResourceRegistryLoader> {
@Override
- public Int2ObjectMap load(Pair input) {
- Int2ObjectMap collisions = new Int2ObjectOpenHashMap<>();
-
+ public List load(Pair input) {
Map, CollisionInfo> annotationMap = new IdentityHashMap<>();
for (Class> clazz : FileUtils.getGeneratedClassesForAnnotation(CollisionRemapper.class.getName())) {
GeyserImpl.getInstance().getLogger().debug("Found annotated collision translator: " + clazz.getCanonicalName());
CollisionRemapper collisionRemapper = clazz.getAnnotation(CollisionRemapper.class);
- annotationMap.put(clazz, new CollisionInfo(collisionRemapper, Pattern.compile(collisionRemapper.regex()), Pattern.compile(collisionRemapper.paramRegex())));
+ annotationMap.put(clazz, new CollisionInfo(collisionRemapper, Pattern.compile(collisionRemapper.regex())));
}
// Load collision mappings file
+ int[] indices;
List collisionList;
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input.value())) {
- ArrayNode collisionNode = (ArrayNode) GeyserImpl.JSON_MAPPER.readTree(stream);
- collisionList = loadBoundingBoxes(collisionNode);
+ NbtMap collisionData = (NbtMap) NbtUtils.createGZIPReader(stream).readTag();
+ indices = collisionData.getIntArray("indices");
+ //SuppressWarnings unchecked
+ collisionList = loadBoundingBoxes(collisionData.getList("collisions", NbtType.LIST));
} catch (Exception e) {
throw new AssertionError("Unable to load collision data", e);
}
- BlockMapping[] blockMappings = BlockRegistries.JAVA_BLOCKS.get();
+ List blockStates = BlockRegistries.BLOCK_STATES.get();
+ var collisions = new ObjectArrayList(blockStates.size());
// Map of unique collisions to its instance
Map collisionInstances = new Object2ObjectOpenHashMap<>();
- for (int i = 0; i < blockMappings.length; i++) {
- BlockMapping blockMapping = blockMappings[i];
- if (blockMapping == null) {
- GeyserImpl.getInstance().getLogger().warning("Missing block mapping for Java block " + i);
+ for (int i = 0; i < blockStates.size(); i++) {
+ BlockState state = blockStates.get(i);
+ if (state == null) {
+ GeyserImpl.getInstance().getLogger().warning("Missing block state for Java block " + i);
continue;
}
- BlockCollision newCollision = instantiateCollision(blockMapping, annotationMap, collisionList);
+ BlockCollision newCollision = instantiateCollision(state, annotationMap, indices[i], collisionList);
if (newCollision != null) {
// If there's an existing instance equal to this one, use that instead
@@ -97,33 +100,28 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader, CollisionInfo> annotationMap, List collisionList) {
- String[] blockIdParts = mapping.getJavaIdentifier().split("\\[");
- String blockName = blockIdParts[0].replace("minecraft:", "");
- String params = "";
- if (blockIdParts.length == 2) {
- params = "[" + blockIdParts[1];
- }
- int collisionIndex = mapping.getCollisionIndex();
+ private @Nullable BlockCollision instantiateCollision(BlockState state, Map, CollisionInfo> annotationMap, int collisionIndex, List collisionList) {
+ String blockName = state.block().javaIdentifier().value();
for (Map.Entry, CollisionInfo> collisionRemappers : annotationMap.entrySet()) {
Class> type = collisionRemappers.getKey();
CollisionInfo collisionInfo = collisionRemappers.getValue();
CollisionRemapper annotation = collisionInfo.collisionRemapper;
- if (collisionInfo.pattern.matcher(blockName).find() && collisionInfo.paramsPattern.matcher(params).find()) {
+ if (collisionInfo.pattern.matcher(blockName).find()) {
try {
if (annotation.passDefaultBoxes()) {
// Create an OtherCollision instance and get the bounding boxes
BoundingBox[] defaultBoxes = collisionList.get(collisionIndex);
- return (BlockCollision) type.getDeclaredConstructor(String.class, BoundingBox[].class).newInstance(params, defaultBoxes);
+ return (BlockCollision) type.getDeclaredConstructor(BlockState.class, BoundingBox[].class).newInstance(state, defaultBoxes);
} else {
- return (BlockCollision) type.getDeclaredConstructor(String.class).newInstance(params);
+ return (BlockCollision) type.getDeclaredConstructor(BlockState.class).newInstance(state);
}
} catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException(e);
@@ -138,25 +136,25 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader loadBoundingBoxes(ArrayNode collisionNode) {
+ private List loadBoundingBoxes(List collisionNode) {
List collisions = new ObjectArrayList<>();
for (int collisionIndex = 0; collisionIndex < collisionNode.size(); collisionIndex++) {
- ArrayNode boundingBoxArray = (ArrayNode) collisionNode.get(collisionIndex);
+ @SuppressWarnings("unchecked") NbtList> boundingBoxArray = (NbtList>) collisionNode.get(collisionIndex);
BoundingBox[] boundingBoxes = new BoundingBox[boundingBoxArray.size()];
for (int i = 0; i < boundingBoxArray.size(); i++) {
- ArrayNode boxProperties = (ArrayNode) boundingBoxArray.get(i);
- boundingBoxes[i] = new BoundingBox(boxProperties.get(0).asDouble(),
- boxProperties.get(1).asDouble(),
- boxProperties.get(2).asDouble(),
- boxProperties.get(3).asDouble(),
- boxProperties.get(4).asDouble(),
- boxProperties.get(5).asDouble());
+ NbtList boxProperties = boundingBoxArray.get(i);
+ boundingBoxes[i] = new BoundingBox(boxProperties.get(0),
+ boxProperties.get(1),
+ boxProperties.get(2),
+ boxProperties.get(3),
+ boxProperties.get(4),
+ boxProperties.get(5));
}
// Sorting by lowest Y first fixes some bugs
@@ -173,6 +171,5 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader {
- NbtMapBuilder updated = context.update(tag, 0).toBuilder();
- updated.remove("version"); // we already removed this, but the context adds it. remove it again.
- return updated.build();
- };
- }
}
public static void populate(Stage stage) {
switch (stage) {
- case PRE_INIT, POST_INIT -> nullifyBlocksNode();
+ case PRE_INIT, POST_INIT -> nullifyBlocksNbt();
case INIT_JAVA -> registerJavaBlocks();
case INIT_BEDROCK -> registerBedrockBlocks();
default -> throw new IllegalArgumentException("Unknown stage: " + stage);
@@ -107,24 +95,20 @@ public final class BlockRegistryPopulator {
}
/**
- * Stores the raw blocks JSON until it is no longer needed.
+ * Stores the raw blocks NBT until it is no longer needed.
*/
- private static JsonNode BLOCKS_JSON;
+ private static List BLOCKS_NBT;
private static int MIN_CUSTOM_RUNTIME_ID = -1;
private static int JAVA_BLOCKS_SIZE = -1;
- private static void nullifyBlocksNode() {
- BLOCKS_JSON = null;
+ private static void nullifyBlocksNbt() {
+ BLOCKS_NBT = null;
}
private static void registerBedrockBlocks() {
var blockMappers = ImmutableMap., Remapper>builder()
- .put(ObjectIntPair.of("1_20_40", Bedrock_v622.CODEC.getProtocolVersion()), Conversion630_622::remapBlock)
- .put(ObjectIntPair.of("1_20_50", Bedrock_v630.CODEC.getProtocolVersion()), Conversion649_630::remapBlock)
- // Only changes in 1.20.60 are hard_stained_glass (an EDU only block)
- .put(ObjectIntPair.of("1_20_60", Bedrock_v649.CODEC.getProtocolVersion()), Conversion662_649::remapBlock)
- .put(ObjectIntPair.of("1_20_70", Bedrock_v662.CODEC.getProtocolVersion()), Conversion671_662::remapBlock)
- .put(ObjectIntPair.of("1_20_80", Bedrock_v671.CODEC.getProtocolVersion()), tag -> tag)
+ .put(ObjectIntPair.of("1_20_80", Bedrock_v671.CODEC.getProtocolVersion()), Conversion685_671::remapBlock)
+ .put(ObjectIntPair.of("1_21_0", Bedrock_v685.CODEC.getProtocolVersion()), tag -> tag)
.build();
// We can keep this strong as nothing should be garbage collected
@@ -215,19 +199,34 @@ public final class BlockRegistryPopulator {
int javaRuntimeId = -1;
+ List javaBlockStates = BlockRegistries.BLOCK_STATES.get();
+
GeyserBedrockBlock airDefinition = null;
BlockDefinition commandBlockDefinition = null;
BlockDefinition mobSpawnerBlockDefinition = null;
BlockDefinition waterDefinition = null;
BlockDefinition movingBlockDefinition = null;
- Iterator> blocksIterator = BLOCKS_JSON.fields();
+ Iterator blocksIterator = BLOCKS_NBT.iterator();
Remapper stateMapper = blockMappers.get(palette);
GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE];
GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE];
- Map flowerPotBlocks = new Object2ObjectOpenHashMap<>();
+ var javaToBedrockIdentifiers = new Int2ObjectOpenHashMap();
+ Block lastBlockSeen = null;
+
+ // Stream isn't ideal.
+ List javaPottable = BlockRegistries.JAVA_BLOCKS.get()
+ .parallelStream()
+ .flatMap(block -> {
+ if (block instanceof FlowerPotBlock flowerPot && flowerPot.flower() != Blocks.AIR) {
+ return Stream.of(flowerPot.flower());
+ }
+ return null;
+ })
+ .toList();
+ Map flowerPotBlocks = new Object2ObjectOpenHashMap<>();
Map itemFrames = new Object2ObjectOpenHashMap<>();
Set jigsawDefinitions = new ObjectOpenHashSet<>();
@@ -236,10 +235,11 @@ public final class BlockRegistryPopulator {
BlockMappings.BlockMappingsBuilder builder = BlockMappings.builder();
while (blocksIterator.hasNext()) {
javaRuntimeId++;
- Map.Entry entry = blocksIterator.next();
- String javaId = entry.getKey();
+ NbtMap entry = blocksIterator.next();
+ BlockState blockState = javaBlockStates.get(javaRuntimeId);
+ String javaId = blockState.toString();
- NbtMap originalBedrockTag = buildBedrockState(entry.getValue());
+ NbtMap originalBedrockTag = buildBedrockState(blockState, entry);
NbtMap bedrockTag = stateMapper.remap(originalBedrockTag);
GeyserBedrockBlock vanillaBedrockDefinition = blockStateOrderedMap.get(bedrockTag);
@@ -271,35 +271,36 @@ public final class BlockRegistryPopulator {
case "minecraft:moving_piston[facing=north,type=normal]" -> movingBlockDefinition = bedrockDefinition;
}
- if (javaId.contains("jigsaw")) {
- jigsawDefinitions.add(bedrockDefinition);
- }
-
- if (javaId.contains("structure_block")) {
- int modeIndex = javaId.indexOf("mode=");
- if (modeIndex != -1) {
- int startIndex = modeIndex + 5; // Length of "mode=" is 5
- int endIndex = javaId.indexOf("]", startIndex);
- if (endIndex != -1) {
- String modeValue = javaId.substring(startIndex, endIndex);
- structureBlockDefinitions.put(modeValue.toUpperCase(), bedrockDefinition);
- }
+ Block block = blockState.block();
+ if (block != lastBlockSeen) {
+ lastBlockSeen = block;
+ String bedrockName = bedrockDefinition.getState().getString("name");
+ if (!block.javaIdentifier().toString().equals(bedrockName)) {
+ javaToBedrockIdentifiers.put(block.javaId(), bedrockName.substring("minecraft:".length()).intern());
}
}
- boolean waterlogged = entry.getKey().contains("waterlogged=true")
- || javaId.contains("minecraft:bubble_column") || javaId.contains("minecraft:kelp") || javaId.contains("seagrass");
-
- if (waterlogged) {
- int finalJavaRuntimeId = javaRuntimeId;
- BlockRegistries.WATERLOGGED.register(set -> set.set(finalJavaRuntimeId));
+ if (block == Blocks.JIGSAW) {
+ jigsawDefinitions.add(bedrockDefinition);
}
- String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(entry.getKey());
+ if (block == Blocks.STRUCTURE_BLOCK) {
+ String mode = blockState.getValue(Properties.STRUCTUREBLOCK_MODE);
+ structureBlockDefinitions.put(mode.toUpperCase(Locale.ROOT), bedrockDefinition);
+ }
+
+ boolean waterlogged = blockState.getValue(Properties.WATERLOGGED, false)
+ || block == Blocks.BUBBLE_COLUMN || block == Blocks.KELP || block == Blocks.KELP_PLANT
+ || block == Blocks.SEAGRASS || block == Blocks.TALL_SEAGRASS;
+
+ if (waterlogged) {
+ BlockRegistries.WATERLOGGED.get().set(javaRuntimeId);
+ }
// Get the tag needed for non-empty flower pots
- if (entry.getValue().get("pottable") != null) {
- flowerPotBlocks.put(cleanJavaIdentifier.intern(), blockStates.get(bedrockDefinition.getRuntimeId()));
+ if (javaPottable.contains(block)) {
+ // Specifically NOT putIfAbsent - mangrove propagule breaks otherwise
+ flowerPotBlocks.put(block, blockStates.get(bedrockDefinition.getRuntimeId()));
}
javaToVanillaBedrockBlocks[javaRuntimeId] = vanillaBedrockDefinition;
@@ -355,9 +356,12 @@ public final class BlockRegistryPopulator {
javaToVanillaBedrockBlocks[stateRuntimeId] = bedrockDefinition; // TODO: Check this?
javaToBedrockBlocks[stateRuntimeId] = bedrockDefinition;
+ javaToBedrockIdentifiers.put(entry.getKey().stateGroupId(), entry.getValue().block().identifier());
}
}
+ javaToBedrockIdentifiers.trim();
+
// Loop around again to find all item frame runtime IDs
Object2ObjectMaps.fastForEach(blockStateOrderedMap, entry -> {
String name = entry.getKey().getString("name");
@@ -369,6 +373,7 @@ public final class BlockRegistryPopulator {
BlockRegistries.BLOCKS.register(palette.valueInt(), builder.bedrockRuntimeMap(bedrockRuntimeMap)
.javaToBedrockBlocks(javaToBedrockBlocks)
.javaToVanillaBedrockBlocks(javaToVanillaBedrockBlocks)
+ .javaToBedrockIdentifiers(javaToBedrockIdentifiers)
.stateDefinitionMap(blockStateOrderedMap)
.itemFrames(itemFrames)
.flowerPotBlocks(flowerPotBlocks)
@@ -383,208 +388,81 @@ public final class BlockRegistryPopulator {
}
private static void registerJavaBlocks() {
- JsonNode blocksJson;
- try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/blocks.json")) {
- blocksJson = GeyserImpl.JSON_MAPPER.readTree(stream);
+ List blocksNbt;
+ try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/blocks.nbt")) {
+ blocksNbt = ((NbtMap) NbtUtils.createGZIPReader(stream).readTag())
+ .getList("bedrock_mappings", NbtType.COMPOUND);
} catch (Exception e) {
throw new AssertionError("Unable to load Java block mappings", e);
}
- JAVA_BLOCKS_SIZE = blocksJson.size();
+ JAVA_BLOCKS_SIZE = BlockRegistries.BLOCK_STATES.get().size();
if (!BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().isEmpty()) {
MIN_CUSTOM_RUNTIME_ID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().min(Comparator.comparing(JavaBlockState::javaId)).orElseThrow().javaId();
int maxCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().max(Comparator.comparing(JavaBlockState::javaId)).orElseThrow().javaId();
- if (MIN_CUSTOM_RUNTIME_ID < blocksJson.size()) {
+ if (MIN_CUSTOM_RUNTIME_ID < blocksNbt.size()) {
throw new RuntimeException("Non vanilla custom block state overrides runtime ID must start after the last vanilla block state (" + JAVA_BLOCKS_SIZE + ")");
}
JAVA_BLOCKS_SIZE = maxCustomRuntimeID + 1; // Runtime ids start at 0, so we need to add 1
}
- BlockRegistries.JAVA_BLOCKS.set(new BlockMapping[JAVA_BLOCKS_SIZE]); // Set array size to number of blockstates
-
- Deque cleanIdentifiers = new ArrayDeque<>();
-
int javaRuntimeId = -1;
- int cobwebBlockId = -1;
- int furnaceRuntimeId = -1;
- int furnaceLitRuntimeId = -1;
- int honeyBlockRuntimeId = -1;
- int slimeBlockRuntimeId = -1;
- int spawnerRuntimeId = -1;
- int uniqueJavaId = -1;
- int waterRuntimeId = -1;
- Iterator> blocksIterator = blocksJson.fields();
- while (blocksIterator.hasNext()) {
+ for (BlockState javaBlockState : BlockRegistries.BLOCK_STATES.get()) {
javaRuntimeId++;
- Map.Entry entry = blocksIterator.next();
- String javaId = entry.getKey();
-
- // TODO fix this, (no block should have a null hardness)
- BlockMapping.BlockMappingBuilder builder = BlockMapping.builder();
- JsonNode hardnessNode = entry.getValue().get("block_hardness");
- if (hardnessNode != null) {
- builder.hardness(hardnessNode.floatValue());
- }
-
- JsonNode canBreakWithHandNode = entry.getValue().get("can_break_with_hand");
- if (canBreakWithHandNode != null) {
- builder.canBreakWithHand(canBreakWithHandNode.booleanValue());
- } else {
- builder.canBreakWithHand(false);
- }
-
- JsonNode collisionIndexNode = entry.getValue().get("collision_index");
- if (hardnessNode != null) {
- builder.collisionIndex(collisionIndexNode.intValue());
- }
-
- JsonNode pickItemNode = entry.getValue().get("pick_item");
- if (pickItemNode != null) {
- builder.pickItem(pickItemNode.textValue().intern());
- }
-
- if (javaId.equals("minecraft:obsidian") || javaId.equals("minecraft:crying_obsidian") || javaId.startsWith("minecraft:respawn_anchor") || javaId.startsWith("minecraft:reinforced_deepslate")) {
- builder.pistonBehavior(PistonBehavior.BLOCK);
- } else {
- JsonNode pistonBehaviorNode = entry.getValue().get("piston_behavior");
- if (pistonBehaviorNode != null) {
- builder.pistonBehavior(PistonBehavior.getByName(pistonBehaviorNode.textValue()));
- } else {
- builder.pistonBehavior(PistonBehavior.NORMAL);
- }
- }
-
- JsonNode hasBlockEntityNode = entry.getValue().get("has_block_entity");
- if (hasBlockEntityNode != null) {
- builder.isBlockEntity(hasBlockEntityNode.booleanValue());
- } else {
- builder.isBlockEntity(false);
- }
-
- BlockStateValues.storeBlockStateValues(entry.getKey(), javaRuntimeId, entry.getValue());
-
- String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(entry.getKey());
- String bedrockIdentifier = entry.getValue().get("bedrock_identifier").asText();
-
- if (!cleanJavaIdentifier.equals(cleanIdentifiers.peekLast())) {
- uniqueJavaId++;
- cleanIdentifiers.add(cleanJavaIdentifier.intern());
- }
-
- builder.javaIdentifier(javaId);
- builder.javaBlockId(uniqueJavaId);
+ String javaId = javaBlockState.toString().intern();
BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, javaRuntimeId);
- BlockRegistries.JAVA_BLOCKS.register(javaRuntimeId, builder.build());
-
- // Keeping this here since this is currently unchanged between versions
- // It's possible to only have this store differences in names, but the key set of all Java names is used in sending command suggestions
- BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.register(cleanJavaIdentifier.intern(), bedrockIdentifier.intern());
-
- if (javaId.contains("cobweb")) {
- cobwebBlockId = uniqueJavaId;
-
- } else if (javaId.startsWith("minecraft:furnace[facing=north")) {
- if (javaId.contains("lit=true")) {
- furnaceLitRuntimeId = javaRuntimeId;
- } else {
- furnaceRuntimeId = javaRuntimeId;
- }
-
- } else if (javaId.startsWith("minecraft:spawner")) {
- spawnerRuntimeId = javaRuntimeId;
-
- } else if ("minecraft:water[level=0]".equals(javaId)) {
- waterRuntimeId = javaRuntimeId;
- } else if (javaId.equals("minecraft:honey_block")) {
- honeyBlockRuntimeId = javaRuntimeId;
- } else if (javaId.equals("minecraft:slime_block")) {
- slimeBlockRuntimeId = javaRuntimeId;
- }
}
- if (cobwebBlockId == -1) {
- throw new AssertionError("Unable to find cobwebs in palette");
- }
- BlockStateValues.JAVA_COBWEB_ID = cobwebBlockId;
-
- if (furnaceRuntimeId == -1) {
- throw new AssertionError("Unable to find furnace in palette");
- }
- BlockStateValues.JAVA_FURNACE_ID = furnaceRuntimeId;
-
- if (furnaceLitRuntimeId == -1) {
- throw new AssertionError("Unable to find lit furnace in palette");
- }
- BlockStateValues.JAVA_FURNACE_LIT_ID = furnaceLitRuntimeId;
-
- if (honeyBlockRuntimeId == -1) {
- throw new AssertionError("Unable to find honey block in palette");
- }
- BlockStateValues.JAVA_HONEY_BLOCK_ID = honeyBlockRuntimeId;
-
- if (slimeBlockRuntimeId == -1) {
- throw new AssertionError("Unable to find slime block in palette");
- }
- BlockStateValues.JAVA_SLIME_BLOCK_ID = slimeBlockRuntimeId;
-
- if (spawnerRuntimeId == -1) {
- throw new AssertionError("Unable to find spawner in palette");
- }
- BlockStateValues.JAVA_SPAWNER_ID = spawnerRuntimeId;
-
- if (waterRuntimeId == -1) {
- throw new AssertionError("Unable to find Java water in palette");
- }
- BlockStateValues.JAVA_WATER_ID = waterRuntimeId;
-
if (!BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().isEmpty()) {
- Set usedNonVanillaRuntimeIDs = new HashSet<>();
+ IntSet usedNonVanillaRuntimeIDs = new IntOpenHashSet();
for (JavaBlockState javaBlockState : BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet()) {
if (!usedNonVanillaRuntimeIDs.add(javaBlockState.javaId())) {
throw new RuntimeException("Duplicate runtime ID " + javaBlockState.javaId() + " for non vanilla Java block state " + javaBlockState.identifier());
}
- CustomBlockState customBlockState = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().get(javaBlockState);
-
String javaId = javaBlockState.identifier();
int stateRuntimeId = javaBlockState.javaId();
String pistonBehavior = javaBlockState.pistonBehavior();
- BlockMapping blockMapping = BlockMapping.builder()
- .canBreakWithHand(javaBlockState.canBreakWithHand())
- .pickItem(javaBlockState.pickItem())
- .isNonVanilla(true)
- .javaIdentifier(javaId)
- .javaBlockId(javaBlockState.stateGroupId())
- .hardness(javaBlockState.blockHardness())
- .pistonBehavior(pistonBehavior == null ? PistonBehavior.NORMAL : PistonBehavior.getByName(pistonBehavior))
- .isBlockEntity(javaBlockState.hasBlockEntity())
- .build();
- String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(javaBlockState.identifier());
- String bedrockIdentifier = customBlockState.block().identifier();
-
- if (!cleanJavaIdentifier.equals(cleanIdentifiers.peekLast())) {
- uniqueJavaId++;
- cleanIdentifiers.add(cleanJavaIdentifier.intern());
+ Block.Builder builder = Block.builder()
+ .destroyTime(javaBlockState.blockHardness())
+ .pushReaction(pistonBehavior == null ? PistonBehavior.NORMAL : PistonBehavior.getByName(pistonBehavior));
+ if (!javaBlockState.canBreakWithHand()) {
+ builder.requiresCorrectToolForDrops();
}
+ if (javaBlockState.hasBlockEntity()) {
+ builder.setBlockEntity();
+ }
+ String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(javaBlockState.identifier());
+ String pickItem = javaBlockState.pickItem();
+ Block block = new Block(cleanJavaIdentifier, builder) {
+ @Override
+ public ItemStack pickItem(BlockState state) {
+ if (this.item == null) {
+ this.item = Registries.JAVA_ITEM_IDENTIFIERS.get(pickItem);
+ if (this.item == null) {
+ GeyserImpl.getInstance().getLogger().warning("We could not find item " + pickItem
+ + " for getting the item for block " + javaBlockState.identifier());
+ this.item = Items.AIR;
+ }
+ }
+ return new ItemStack(this.item.javaId());
+ }
+ };
+ block.setJavaId(javaBlockState.stateGroupId());
+ BlockRegistries.JAVA_BLOCKS.registerWithAnyIndex(javaBlockState.stateGroupId(), block, Blocks.AIR);
BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, stateRuntimeId);
- BlockRegistries.JAVA_BLOCKS.register(stateRuntimeId, blockMapping);
-
- // Keeping this here since this is currently unchanged between versions
- // It's possible to only have this store differences in names, but the key set of all Java names is used in sending command suggestions
- BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.register(cleanJavaIdentifier.intern(), bedrockIdentifier.intern());
+ BlockRegistries.BLOCK_STATES.register(stateRuntimeId, new BlockState(block, stateRuntimeId));
}
}
- BlockRegistries.CLEAN_JAVA_IDENTIFIERS.set(cleanIdentifiers.toArray(new String[0]));
-
- BLOCKS_JSON = blocksJson;
+ BLOCKS_NBT = blocksNbt;
JsonNode blockInteractionsJson;
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/interactions.json")) {
@@ -595,6 +473,8 @@ public final class BlockRegistryPopulator {
BlockRegistries.INTERACTIVE.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("always_consumes")));
BlockRegistries.INTERACTIVE_MAY_BUILD.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("requires_may_build")));
+
+ BlockRegistries.BLOCK_STATES.freeze();
}
private static BitSet toBlockStateSet(ArrayNode node) {
@@ -605,29 +485,11 @@ public final class BlockRegistryPopulator {
return blockStateSet;
}
- private static NbtMap buildBedrockState(JsonNode node) {
+ private static NbtMap buildBedrockState(BlockState state, NbtMap nbt) {
NbtMapBuilder tagBuilder = NbtMap.builder();
- String bedrockIdentifier = node.get("bedrock_identifier").textValue();
+ String bedrockIdentifier = "minecraft:" + nbt.getString("bedrock_identifier", state.block().javaIdentifier().value());
tagBuilder.putString("name", bedrockIdentifier);
-
- NbtMapBuilder statesBuilder = NbtMap.builder();
-
- // check for states
- JsonNode states = node.get("bedrock_states");
- if (states != null) {
- Iterator> statesIterator = states.fields();
-
- while (statesIterator.hasNext()) {
- Map.Entry stateEntry = statesIterator.next();
- JsonNode stateValue = stateEntry.getValue();
- switch (stateValue.getNodeType()) {
- case BOOLEAN -> statesBuilder.putBoolean(stateEntry.getKey(), stateValue.booleanValue());
- case STRING -> statesBuilder.putString(stateEntry.getKey(), stateValue.textValue());
- case NUMBER -> statesBuilder.putInt(stateEntry.getKey(), stateValue.intValue());
- }
- }
- }
- tagBuilder.put("states", statesBuilder.build());
+ tagBuilder.put("states", nbt.getCompound("state"));
return tagBuilder.build();
}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java
deleted file mode 100644
index 398eabc3c..000000000
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-
-package org.geysermc.geyser.registry.populator;
-
-import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
-import org.cloudburstmc.nbt.NbtMap;
-import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.geyser.item.type.Item;
-import org.geysermc.geyser.registry.type.GeyserMappingItem;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Backwards-maps the blocks and items of 1.20.50 (630) to 1.20.40 (622)
- */
-class Conversion630_622 {
-
- private static final List NEW_STONES = List.of("minecraft:stone", "minecraft:granite", "minecraft:polished_granite", "minecraft:diorite", "minecraft:polished_diorite", "minecraft:andesite", "minecraft:polished_andesite");
- private static final List NEW_WOODS = List.of("minecraft:oak_planks", "minecraft:spruce_planks", "minecraft:birch_planks", "minecraft:jungle_planks", "minecraft:acacia_planks", "minecraft:dark_oak_planks");
-
- private static final Map ITEMS = new Object2ObjectOpenHashMap<>();
-
- static {
- ITEMS.put("minecraft:acacia_planks", "minecraft:planks");
- ITEMS.put("minecraft:birch_planks", "minecraft:planks");
- ITEMS.put("minecraft:dark_oak_planks", "minecraft:planks");
- ITEMS.put("minecraft:jungle_planks", "minecraft:planks");
- ITEMS.put("minecraft:oak_planks", "minecraft:planks");
- ITEMS.put("minecraft:spruce_planks", "minecraft:planks");
-
- ITEMS.put("minecraft:diorite", "minecraft:stone");
- ITEMS.put("minecraft:andesite", "minecraft:stone");
- ITEMS.put("minecraft:granite", "minecraft:stone");
- ITEMS.put("minecraft:polished_andesite", "minecraft:stone");
- ITEMS.put("minecraft:polished_diorite", "minecraft:stone");
- ITEMS.put("minecraft:polished_granite", "minecraft:stone");
-
- ITEMS.put("minecraft:chiseled_tuff", "minecraft:chiseled_deepslate");
- ITEMS.put("minecraft:chiseled_tuff_bricks", "minecraft:chiseled_deepslate");
- ITEMS.put("minecraft:polished_tuff", "minecraft:polished_deepslate");
- ITEMS.put("minecraft:polished_tuff_double_slab", "minecraft:polished_deepslate_double_slab");
- ITEMS.put("minecraft:polished_tuff_slab", "minecraft:polished_deepslate_slab");
- ITEMS.put("minecraft:polished_tuff_stairs", "minecraft:polished_deepslate_stairs");
- ITEMS.put("minecraft:polished_tuff_wall", "minecraft:polished_deepslate_wall");
- ITEMS.put("minecraft:tuff_brick_double_slab", "minecraft:deepslate_brick_double_slab");
- ITEMS.put("minecraft:tuff_brick_slab", "minecraft:deepslate_brick_slab");
- ITEMS.put("minecraft:tuff_brick_stairs", "minecraft:deepslate_brick_stairs");
- ITEMS.put("minecraft:tuff_brick_wall", "minecraft:deepslate_brick_wall");
- ITEMS.put("minecraft:tuff_bricks", "minecraft:deepslate_bricks");
- ITEMS.put("minecraft:tuff_double_slab", "minecraft:cobbled_deepslate_double_slab");
- ITEMS.put("minecraft:tuff_slab", "minecraft:cobbled_deepslate_slab");
- ITEMS.put("minecraft:tuff_stairs", "minecraft:cobbled_deepslate_stairs");
- ITEMS.put("minecraft:tuff_wall", "minecraft:cobbled_deepslate_wall");
-
- ITEMS.put("minecraft:chiseled_copper", "minecraft:copper_block");
- ITEMS.put("minecraft:copper_bulb", "minecraft:copper_block");
- ITEMS.put("minecraft:copper_door", "minecraft:iron_door");
- ITEMS.put("minecraft:copper_grate", "minecraft:raw_iron_block");
- ITEMS.put("minecraft:copper_trapdoor", "minecraft:iron_trapdoor");
- ITEMS.put("minecraft:exposed_chiseled_copper", "minecraft:exposed_copper");
- ITEMS.put("minecraft:exposed_copper_bulb", "minecraft:exposed_copper");
- ITEMS.put("minecraft:exposed_copper_door", "minecraft:iron_door");
- ITEMS.put("minecraft:exposed_copper_grate", "minecraft:raw_iron_block");
- ITEMS.put("minecraft:exposed_copper_trapdoor", "minecraft:iron_trapdoor");
- ITEMS.put("minecraft:oxidized_chiseled_copper", "minecraft:oxidized_copper");
- ITEMS.put("minecraft:oxidized_copper_bulb", "minecraft:oxidized_copper");
- ITEMS.put("minecraft:oxidized_copper_door", "minecraft:iron_door");
- ITEMS.put("minecraft:oxidized_copper_grate", "minecraft:raw_iron_block");
- ITEMS.put("minecraft:oxidized_copper_trapdoor", "minecraft:iron_trapdoor");
- ITEMS.put("minecraft:waxed_chiseled_copper", "minecraft:waxed_copper");
- ITEMS.put("minecraft:waxed_copper_bulb", "minecraft:waxed_copper");
- ITEMS.put("minecraft:waxed_copper_door", "minecraft:iron_door");
- ITEMS.put("minecraft:waxed_copper_grate", "minecraft:raw_iron_block");
- ITEMS.put("minecraft:waxed_copper_trapdoor", "minecraft:iron_trapdoor");
- ITEMS.put("minecraft:waxed_exposed_chiseled_copper", "minecraft:waxed_exposed_copper");
- ITEMS.put("minecraft:waxed_exposed_copper_bulb", "minecraft:waxed_exposed_copper");
- ITEMS.put("minecraft:waxed_exposed_copper_door", "minecraft:iron_door");
- ITEMS.put("minecraft:waxed_exposed_copper_grate", "minecraft:raw_iron_block");
- ITEMS.put("minecraft:waxed_exposed_copper_trapdoor", "minecraft:iron_trapdoor");
- ITEMS.put("minecraft:waxed_oxidized_chiseled_copper", "minecraft:waxed_oxidized_copper");
- ITEMS.put("minecraft:waxed_oxidized_copper_bulb", "minecraft:waxed_oxidized_copper");
- ITEMS.put("minecraft:waxed_oxidized_copper_door", "minecraft:iron_door");
- ITEMS.put("minecraft:waxed_oxidized_copper_grate", "minecraft:raw_iron_block");
- ITEMS.put("minecraft:waxed_oxidized_copper_trapdoor", "minecraft:iron_trapdoor");
- ITEMS.put("minecraft:waxed_weathered_chiseled_copper", "minecraft:waxed_weathered_copper");
- ITEMS.put("minecraft:waxed_weathered_copper_bulb", "minecraft:waxed_weathered_copper");
- ITEMS.put("minecraft:waxed_weathered_copper_door", "minecraft:iron_door");
- ITEMS.put("minecraft:waxed_weathered_copper_grate", "minecraft:raw_iron_block");
- ITEMS.put("minecraft:waxed_weathered_copper_trapdoor", "minecraft:iron_trapdoor");
- ITEMS.put("minecraft:weathered_chiseled_copper", "minecraft:weathered_copper");
- ITEMS.put("minecraft:weathered_copper_bulb", "minecraft:weathered_copper");
- ITEMS.put("minecraft:weathered_copper_door", "minecraft:iron_door");
- ITEMS.put("minecraft:weathered_copper_grate", "minecraft:raw_iron_block");
- ITEMS.put("minecraft:weathered_copper_trapdoor", "minecraft:iron_trapdoor");
-
- ITEMS.put("minecraft:crafter", "minecraft:crafting_table");
- }
-
- static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) {
- mapping = Conversion649_630.remapItem(item, mapping);
-
- String replacement = ITEMS.get(mapping.getBedrockIdentifier());
- if (replacement == null) {
- return mapping;
- } else {
- return mapping.withBedrockIdentifier(replacement);
- }
- }
-
- static NbtMap remapBlock(NbtMap tag) {
- tag = Conversion649_630.remapBlock(tag);
-
- final String name = tag.getString("name");
-
- String replacement;
- if (NEW_STONES.contains(name) || NEW_WOODS.contains(name)) {
-
- String typeKey;
- String type = name.substring(10);
- if (NEW_STONES.contains(name)) {
- replacement = "minecraft:stone";
- typeKey = "stone_type";
- if (type.startsWith("polished_")) {
- type = type.substring(9) + "_smooth";
- }
- } else {
- replacement = "minecraft:planks";
- typeKey = "wood_type";
- type = type.substring(0, type.indexOf("_planks"));
- }
-
- return tag.toBuilder()
- .putString("name", replacement)
- .putCompound("states", NbtMap.builder().putString(typeKey, type).build())
- .build();
- } else if (name.contains("tuff") && !name.equals("minecraft:tuff")) {
-
- if (name.contains("brick") || name.contains("polished") || name.contains("chiseled")) {
- replacement = name.replace("tuff", "deepslate");
-
- if (name.contains("chiseled")) {
- // chiseled deepslate bricks don't exist. just use chiseled deepslate instead
- replacement = replacement.replace("_bricks", "");
- }
- } else {
- replacement = name.replace("tuff", "cobbled_deepslate");
- }
-
- return tag.toBuilder()
- .putString("name", replacement)
- .build();
- } else if (name.contains("copper")) {
-
- boolean removeStates = false;
- if (name.contains("chiseled")) {
- replacement = name.replace("_chiseled", ""); // special chiseled
- replacement = replacement.replace("chiseled_", ""); // plain chiseled
- } else if (name.endsWith("bulb")) {
- replacement = name.replace("_bulb", "");
- removeStates = true;
- } else if (name.endsWith("grate")) {
- replacement = "minecraft:raw_iron_block";
- } else if (name.endsWith("door")) {
- if (name.contains("trap")) {
- replacement = "minecraft:iron_trapdoor";
- } else {
- replacement = "minecraft:iron_door";
- }
- } else {
- return tag;
- }
-
- if (replacement.endsWith(":copper")) {
- // case for plain chiseled copper and plain bulb
- replacement = replacement + "_block";
- }
-
- NbtMapBuilder builder = tag.toBuilder();
- builder.putString("name", replacement);
- if (removeStates) {
- builder.putCompound("states", NbtMap.EMPTY);
- }
- return builder.build();
- } else if (name.equals("minecraft:crafter")) {
- NbtMapBuilder builder = tag.toBuilder();
- builder.put("name", "minecraft:crafting_table");
- builder.put("states", NbtMap.EMPTY);
- return builder.build();
- }
-
- return tag;
- }
-}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java
deleted file mode 100644
index 70a5e1ad9..000000000
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-package org.geysermc.geyser.registry.populator;
-
-import org.cloudburstmc.nbt.NbtMap;
-import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.geyser.item.type.Item;
-import org.geysermc.geyser.registry.type.GeyserMappingItem;
-
-public class Conversion649_630 {
-
- static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) {
- mapping = Conversion662_649.remapItem(item, mapping);
-
- String identifer = mapping.getBedrockIdentifier();
-
- switch (identifer) {
- case "minecraft:armadillo_scute", "minecraft:turtle_scute" -> { return mapping.withBedrockIdentifier("minecraft:scute"); }
- case "minecraft:armadillo_spawn_egg" -> { return mapping.withBedrockIdentifier("minecraft:rabbit_spawn_egg"); }
- case "minecraft:trial_spawner" -> { return mapping.withBedrockIdentifier("minecraft:mob_spawner"); }
- case "minecraft:trial_key" -> { return mapping.withBedrockIdentifier("minecraft:echo_shard"); }
- case "minecraft:wolf_armor" -> { return mapping.withBedrockIdentifier("minecraft:leather_horse_armor"); }
- default -> { return mapping; }
- }
- }
-
- static NbtMap remapBlock(NbtMap tag) {
- tag = Conversion662_649.remapBlock(tag);
-
- final String name = tag.getString("name");
-
- if (name.equals("minecraft:trial_spawner")) {
- NbtMapBuilder builder = tag.toBuilder()
- .putString("name", "minecraft:mob_spawner")
- .putCompound("states", NbtMap.EMPTY);
-
- return builder.build();
- }
-
- return tag;
- }
-}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java
deleted file mode 100644
index 041afdbc8..000000000
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-
-package org.geysermc.geyser.registry.populator;
-
-import org.cloudburstmc.nbt.NbtMap;
-import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.geyser.item.type.Item;
-import org.geysermc.geyser.registry.type.GeyserMappingItem;
-
-import java.util.List;
-import java.util.stream.Stream;
-
-public class Conversion662_649 {
-
- private static final List NEW_MISC = List.of("minecraft:grass_block", "minecraft:vault");
- private static final List NEW_WOODS = List.of("minecraft:oak_wood", "minecraft:spruce_wood", "minecraft:birch_wood", "minecraft:jungle_wood", "minecraft:acacia_wood", "minecraft:dark_oak_wood", "minecraft:stripped_oak_wood", "minecraft:stripped_spruce_wood", "minecraft:stripped_birch_wood", "minecraft:stripped_jungle_wood", "minecraft:stripped_acacia_wood", "minecraft:stripped_dark_oak_wood");
- private static final List NEW_LEAVES = List.of("minecraft:oak_leaves", "minecraft:spruce_leaves", "minecraft:birch_leaves", "minecraft:jungle_leaves");
- private static final List NEW_LEAVES2 = List.of("minecraft:acacia_leaves", "minecraft:dark_oak_leaves");
- private static final List NEW_SLABS = List.of("minecraft:oak_slab", "minecraft:spruce_slab", "minecraft:birch_slab", "minecraft:jungle_slab", "minecraft:acacia_slab", "minecraft:dark_oak_slab", "minecraft:oak_double_slab", "minecraft:spruce_double_slab", "minecraft:birch_double_slab", "minecraft:jungle_double_slab", "minecraft:acacia_double_slab", "minecraft:dark_oak_double_slab");
- private static final List NEW_BLOCKS = Stream.of(NEW_WOODS, NEW_LEAVES, NEW_LEAVES2, NEW_SLABS, NEW_MISC).flatMap(List::stream).toList();
-
-
- static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) {
- mapping = Conversion671_662.remapItem(item, mapping);
-
- String identifer = mapping.getBedrockIdentifier();
-
- switch (identifer) {
- case "minecraft:bogged_spawn_egg" -> { return mapping.withBedrockIdentifier("minecraft:creeper_spawn_egg"); }
- case "minecraft:grass_block" -> { return mapping.withBedrockIdentifier("minecraft:grass"); }
- case "minecraft:vault" -> { return mapping.withBedrockIdentifier("minecraft:trial_spawner"); }
- case "minecraft:wind_charge" -> { return mapping.withBedrockIdentifier("minecraft:snowball"); }
- };
-
- if (NEW_WOODS.contains(identifer)) {
- switch (identifer) {
- case "minecraft:oak_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(0); }
- case "minecraft:spruce_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(1); }
- case "minecraft:birch_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(2); }
- case "minecraft:jungle_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(3); }
- case "minecraft:acacia_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(4); }
- case "minecraft:dark_oak_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(5); }
- case "minecraft:stripped_oak_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(8); }
- case "minecraft:stripped_spruce_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(9); }
- case "minecraft:stripped_birch_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(10); }
- case "minecraft:stripped_jungle_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(11); }
- case "minecraft:stripped_acacia_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(12); }
- case "minecraft:stripped_dark_oak_wood" -> { return mapping.withBedrockIdentifier("minecraft:wood").withBedrockData(13); }
- }
- }
-
- if (NEW_SLABS.contains(identifer)) {
- switch (identifer) {
- case "minecraft:oak_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(0); }
- case "minecraft:spruce_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(1); }
- case "minecraft:birch_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(2); }
- case "minecraft:jungle_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(3); }
- case "minecraft:acacia_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(4); }
- case "minecraft:dark_oak_slab" -> { return mapping.withBedrockIdentifier("minecraft:wooden_slab").withBedrockData(5); }
- }
- }
-
- if (NEW_LEAVES.contains(identifer) || NEW_LEAVES2.contains(identifer)) {
- switch (identifer) {
- case "minecraft:oak_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves").withBedrockData(0); }
- case "minecraft:spruce_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves").withBedrockData(1); }
- case "minecraft:birch_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves").withBedrockData(2); }
- case "minecraft:jungle_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves").withBedrockData(3); }
- case "minecraft:acacia_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves2").withBedrockData(0); }
- case "minecraft:dark_oak_leaves" -> { return mapping.withBedrockIdentifier("minecraft:leaves2").withBedrockData(1); }
- }
- }
-
- return mapping;
- }
-
- static NbtMap remapBlock(NbtMap tag) {
- tag = Conversion671_662.remapBlock(tag);
-
- final String name = tag.getString("name");
-
- if (!NEW_BLOCKS.contains(name)) {
- return tag;
- }
-
- String replacement;
-
- if (name.equals("minecraft:grass_block")) {
- replacement = "minecraft:grass";
-
- NbtMapBuilder builder = tag.toBuilder();
- builder.putString("name", replacement);
-
- return builder.build();
- }
-
- if (name.equals("minecraft:vault")) {
- replacement = "minecraft:trial_spawner";
-
- NbtMapBuilder statesBuilder = NbtMap.builder()
- .putInt("trial_spawner_state", 0);
-
- NbtMapBuilder builder = tag.toBuilder();
- builder.putString("name", replacement);
- builder.putCompound("states", statesBuilder.build());
-
- return builder.build();
- }
-
- if (NEW_WOODS.contains(name)) {
- replacement = "minecraft:wood";
-
- NbtMap states = tag.getCompound("states");
- boolean stripped = name.startsWith("minecraft:stripped_");
- String woodType = name.replaceAll("minecraft:|_wood|stripped_", "");
-
- NbtMapBuilder statesBuilder = states.toBuilder()
- .putString("wood_type", woodType)
- .putBoolean("stripped_bit", stripped);
-
- NbtMapBuilder builder = tag.toBuilder()
- .putString("name", replacement)
- .putCompound("states", statesBuilder.build());
-
- return builder.build();
- }
-
- if (NEW_LEAVES.contains(name) || NEW_LEAVES2.contains(name)) {
- boolean leaves2 = NEW_LEAVES2.contains(name);
- replacement = leaves2 ? "minecraft:leaves2" : "minecraft:leaves";
-
- NbtMap states = tag.getCompound("states");
- String leafType = name.replaceAll("minecraft:|_leaves", "");
-
- NbtMapBuilder statesBuilder = states.toBuilder()
- .putString(leaves2 ? "new_leaf_type" : "old_leaf_type", leafType);
-
- NbtMapBuilder builder = tag.toBuilder()
- .putString("name", replacement)
- .putCompound("states", statesBuilder.build());
-
- return builder.build();
- }
-
-
- if (NEW_SLABS.contains(name)) {
- replacement = name.contains("double") ? "minecraft:double_wooden_slab" : "minecraft:wooden_slab";
-
- NbtMap states = tag.getCompound("states");
- String woodType = name.replaceAll("minecraft:|_double|_slab", "");
-
- NbtMapBuilder statesBuilder = states.toBuilder()
- .putString("wood_type", woodType);
-
- NbtMapBuilder builder = tag.toBuilder()
- .putString("name", replacement)
- .putCompound("states", statesBuilder.build());
-
- return builder.build();
- }
-
- return tag;
- }
-}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java
deleted file mode 100644
index 29ab3f2e5..000000000
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-
-package org.geysermc.geyser.registry.populator;
-
-import org.cloudburstmc.nbt.NbtMap;
-import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.geyser.item.type.Item;
-import org.geysermc.geyser.registry.type.GeyserMappingItem;
-
-import java.util.List;
-import java.util.stream.Stream;
-
-public class Conversion671_662 {
- private static final List NEW_MISC = List.of("minecraft:heavy_core", "minecraft:mace", "minecraft:flow_banner_pattern", "minecraft:guster_banner_pattern", "minecraft:flow_armor_trim_smithing_template", "minecraft:bolt_armor_trim_smithing_template", "minecraft:flow_pottery_sherd", "minecraft:guster_pottery_sherd", "minecraft:scrape_pottery_sherd", "minecraft:breeze_rod");
- private static final List NEW_CORAL_FANS = List.of("minecraft:tube_coral_fan", "minecraft:brain_coral_fan", "minecraft:bubble_coral_fan", "minecraft:fire_coral_fan", "minecraft:horn_coral_fan");
- private static final List NEW_DEAD_CORAL_FANS = List.of("minecraft:dead_tube_coral_fan", "minecraft:dead_brain_coral_fan", "minecraft:dead_bubble_coral_fan", "minecraft:dead_fire_coral_fan", "minecraft:dead_horn_coral_fan");
- private static final List NEW_FLOWERS = List.of("minecraft:poppy", "minecraft:blue_orchid", "minecraft:allium", "minecraft:azure_bluet", "minecraft:red_tulip", "minecraft:orange_tulip", "minecraft:white_tulip", "minecraft:pink_tulip", "minecraft:oxeye_daisy", "minecraft:cornflower", "minecraft:lily_of_the_valley");
- private static final List NEW_SAPLINGS = List.of("minecraft:oak_sapling", "minecraft:spruce_sapling", "minecraft:birch_sapling", "minecraft:jungle_sapling", "minecraft:acacia_sapling", "minecraft:dark_oak_sapling", "minecraft:bamboo_sapling");
- private static final List NEW_BLOCKS = Stream.of(NEW_MISC, NEW_CORAL_FANS, NEW_DEAD_CORAL_FANS, NEW_FLOWERS, NEW_SAPLINGS).flatMap(List::stream).toList();
-
- static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) {
- String identifer = mapping.getBedrockIdentifier();
-
- if (!NEW_BLOCKS.contains(identifer)) {
- return mapping;
- }
-
- switch (identifer) {
- case "minecraft:bolt_armor_trim_smithing_template" -> { return mapping.withBedrockIdentifier("minecraft:wayfinder_armor_trim_smithing_template"); }
- case "minecraft:breeze_rod" -> { return mapping.withBedrockIdentifier("minecraft:blaze_rod"); }
- case "minecraft:flow_armor_trim_smithing_template" -> { return mapping.withBedrockIdentifier("minecraft:spire_armor_trim_smithing_template"); }
- case "minecraft:flow_banner_pattern", "minecraft:guster_banner_pattern" -> { return mapping.withBedrockIdentifier("minecraft:globe_banner_pattern"); }
- case "minecraft:flow_pottery_sherd" -> { return mapping.withBedrockIdentifier("minecraft:skull_pottery_sherd"); }
- case "minecraft:guster_pottery_sherd" -> { return mapping.withBedrockIdentifier("minecraft:shelter_pottery_sherd"); }
- case "minecraft:scrape_pottery_sherd" -> { return mapping.withBedrockIdentifier("minecraft:heartbreak_pottery_sherd"); }
- case "minecraft:heavy_core" -> { return mapping.withBedrockIdentifier("minecraft:conduit"); }
- case "minecraft:mace" -> { return mapping.withBedrockIdentifier("minecraft:netherite_axe"); }
- }
-
- if (NEW_FLOWERS.contains(identifer)) {
- switch (identifer) {
- case "minecraft:poppy" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(0); }
- case "minecraft:blue_orchid" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(1); }
- case "minecraft:allium" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(2); }
- case "minecraft:azure_bluet" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(3); }
- case "minecraft:red_tulip" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(4); }
- case "minecraft:orange_tulip" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(5); }
- case "minecraft:white_tulip" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(6); }
- case "minecraft:pink_tulip" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(7); }
- case "minecraft:oxeye_daisy" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(8); }
- case "minecraft:cornflower" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(9); }
- case "minecraft:lily_of_the_valley" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(10); }
- }
- }
-
- if (NEW_SAPLINGS.contains(identifer)) {
- switch (identifer) {
- case "minecraft:oak_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(0); }
- case "minecraft:spruce_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(1); }
- case "minecraft:birch_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(2); }
- case "minecraft:jungle_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(3); }
- case "minecraft:acacia_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(4); }
- case "minecraft:dark_oak_sapling" -> { return mapping.withBedrockIdentifier("minecraft:sapling").withBedrockData(5); }
- }
- }
-
- if (NEW_CORAL_FANS.contains(identifer)) {
- switch (identifer) {
- case "minecraft:tube_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan").withBedrockData(0); }
- case "minecraft:brain_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan").withBedrockData(1); }
- case "minecraft:bubble_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan").withBedrockData(2); }
- case "minecraft:fire_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan").withBedrockData(3); }
- case "minecraft:horn_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan").withBedrockData(4); }
- }
- }
-
- if (NEW_DEAD_CORAL_FANS.contains(identifer)) {
- switch (identifer) {
- case "minecraft:dead_tube_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan_dead").withBedrockData(0); }
- case "minecraft:dead_brain_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan_dead").withBedrockData(1); }
- case "minecraft:dead_bubble_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan_dead").withBedrockData(2); }
- case "minecraft:dead_fire_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan_dead").withBedrockData(3); }
- case "minecraft:dead_horn_coral_fan" -> { return mapping.withBedrockIdentifier("minecraft:coral_fan_dead").withBedrockData(4); }
- }
- }
-
- return mapping;
- }
-
- static NbtMap remapBlock(NbtMap tag) {
- final String name = tag.getString("name");
-
- if (!NEW_BLOCKS.contains(name)) {
- return tag;
- }
-
- if (name.equals("minecraft:bamboo_sapling")) {
- NbtMap states = tag.getCompound("states")
- .toBuilder()
- .putString("sapling_type", "oak")
- .build();
-
- return tag.toBuilder().putCompound("states", states).build();
- }
-
- String replacement;
-
- if (name.equals("minecraft:heavy_core")) {
- replacement = "minecraft:conduit";
-
- NbtMapBuilder builder = tag.toBuilder();
- builder.putString("name", replacement);
-
- return builder.build();
- }
-
- if (NEW_SAPLINGS.contains(name)) {
- replacement = "minecraft:sapling";
- String saplingType = name.replaceAll("minecraft:|_sapling", "");;
-
- NbtMap states = tag.getCompound("states")
- .toBuilder()
- .putString("sapling_type", saplingType)
- .build();
-
- return tag.toBuilder().putString("name", replacement).putCompound("states", states).build();
- }
-
- if (NEW_FLOWERS.contains(name)) {
- replacement = "minecraft:red_flower";
- String flowerType;
-
- switch (name) {
- case "minecraft:poppy" -> flowerType = "poppy";
- case "minecraft:blue_orchid" -> flowerType = "orchid";
- case "minecraft:allium" -> flowerType = "allium";
- case "minecraft:azure_bluet" -> flowerType = "houstonia";
- case "minecraft:red_tulip" -> flowerType = "tulip_red";
- case "minecraft:orange_tulip" -> flowerType = "tulip_orange";
- case "minecraft:white_tulip" -> flowerType = "tulip_white";
- case "minecraft:pink_tulip" -> flowerType = "tulip_pink";
- case "minecraft:oxeye_daisy" -> flowerType = "oxeye";
- case "minecraft:cornflower" -> flowerType = "cornflower";
- case "minecraft:lily_of_the_valley" -> flowerType = "lily_of_the_valley";
- default -> throw new IllegalStateException("Unexpected value: " + name);
- }
-
- NbtMap states = tag.getCompound("states")
- .toBuilder()
- .putString("flower_type", flowerType)
- .build();
-
- return tag.toBuilder().putString("name", replacement).putCompound("states", states).build();
- }
-
- boolean isLiveCoralFan = NEW_CORAL_FANS.contains(name);
- boolean isDeadCoralFan = NEW_DEAD_CORAL_FANS.contains(name);
-
- if (isLiveCoralFan || isDeadCoralFan) {
- replacement = isLiveCoralFan ? "minecraft:coral_fan" : "minecraft:coral_fan_dead";
- String coralColor;
-
- switch (name) {
- case "minecraft:tube_coral_fan", "minecraft:dead_tube_coral_fan" -> coralColor = "blue";
- case "minecraft:brain_coral_fan", "minecraft:dead_brain_coral_fan" -> coralColor = "pink";
- case "minecraft:bubble_coral_fan", "minecraft:dead_bubble_coral_fan" -> coralColor = "purple";
- case "minecraft:fire_coral_fan", "minecraft:dead_fire_coral_fan" -> coralColor = "yellow";
- case "minecraft:horn_coral_fan", "minecraft:dead_horn_coral_fan" -> coralColor = "red";
- default -> throw new IllegalStateException("Unexpected value: " + name);
- }
-
- NbtMap states = tag.getCompound("states")
- .toBuilder()
- .putString("coral_color", coralColor)
- .build();
-
- return tag.toBuilder().putString("name", replacement).putCompound("states", states).build();
- }
-
- return tag;
- }
-}
\ No newline at end of file
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java
new file mode 100644
index 000000000..0b0731707
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.geyser.registry.populator;
+
+import org.cloudburstmc.nbt.NbtMap;
+import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.geysermc.geyser.item.type.Item;
+import org.geysermc.geyser.registry.type.GeyserMappingItem;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+public class Conversion685_671 {
+ private static final List NEW_CORAL_BLOCKS = List.of("minecraft:tube_coral_block", "minecraft:brain_coral_block", "minecraft:bubble_coral_block", "minecraft:fire_coral_block", "minecraft:horn_coral_block", "minecraft:dead_tube_coral_block", "minecraft:dead_brain_coral_block", "minecraft:dead_bubble_coral_block", "minecraft:dead_fire_coral_block", "minecraft:dead_horn_coral_block");
+ private static final List NEW_DOUBLE_PLANTS = List.of("minecraft:sunflower", "minecraft:lilac", "minecraft:tall_grass", "minecraft:large_fern", "minecraft:rose_bush", "minecraft:peony");
+ private static final List NEW_STONE_BLOCK_SLABS = List.of("minecraft:smooth_stone_slab", "minecraft:sandstone_slab", "minecraft:petrified_oak_slab", "minecraft:cobblestone_slab", "minecraft:brick_slab", "minecraft:stone_brick_slab", "minecraft:quartz_slab", "minecraft:nether_brick_slab");
+ private static final List NEW_TALLGRASSES = List.of("minecraft:fern", "minecraft:short_grass");
+ private static final List OMINOUS_BLOCKS = List.of("minecraft:trial_spawner", "minecraft:vault");
+ private static final List NEW_BLOCKS = Stream.of(NEW_CORAL_BLOCKS, NEW_DOUBLE_PLANTS, NEW_STONE_BLOCK_SLABS, NEW_TALLGRASSES).flatMap(List::stream).toList();
+ private static final List MODIFIED_BLOCKS = Stream.of(NEW_BLOCKS, OMINOUS_BLOCKS).flatMap(List::stream).toList();
+
+ static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) {
+ String identifer = mapping.getBedrockIdentifier();
+
+ if (!NEW_BLOCKS.contains(identifer)) {
+ return mapping;
+ }
+
+ if (NEW_CORAL_BLOCKS.contains(identifer)) {
+ switch (identifer) {
+ case "minecraft:tube_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(0); }
+ case "minecraft:brain_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(1); }
+ case "minecraft:bubble_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(2); }
+ case "minecraft:fire_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(3); }
+ case "minecraft:horn_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(4); }
+ case "minecraft:dead_tube_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(8); }
+ case "minecraft:dead_brain_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(9); }
+ case "minecraft:dead_bubble_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(10); }
+ case "minecraft:dead_fire_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(11); }
+ case "minecraft:dead_horn_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(12); }
+ }
+ }
+
+ if (NEW_DOUBLE_PLANTS.contains(identifer)) {
+ switch (identifer) {
+ case "minecraft:sunflower" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(0); }
+ case "minecraft:lilac" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(1); }
+ case "minecraft:tall_grass" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(2); }
+ case "minecraft:large_fern" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(3); }
+ case "minecraft:rose_bush" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(4); }
+ case "minecraft:peony" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(5); }
+ }
+ }
+
+ if (NEW_STONE_BLOCK_SLABS.contains(identifer)) {
+ switch (identifer) {
+ case "minecraft:smooth_stone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(0); }
+ case "minecraft:sandstone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(1); }
+ case "minecraft:petrified_oak_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(2); }
+ case "minecraft:cobblestone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(3); }
+ case "minecraft:brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(4); }
+ case "minecraft:stone_brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(5); }
+ case "minecraft:quartz_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(6); }
+ case "minecraft:nether_brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(7); }
+ }
+ }
+
+ if (NEW_TALLGRASSES.contains(identifer)) {
+ switch (identifer) {
+ case "minecraft:short_grass" -> { return mapping.withBedrockIdentifier("minecraft:tallgrass").withBedrockData(1); }
+ case "minecraft:fern" -> { return mapping.withBedrockIdentifier("minecraft:tallgrass").withBedrockData(2); }
+ }
+ }
+
+ return mapping;
+ }
+
+ static NbtMap remapBlock(NbtMap tag) {
+ final String name = tag.getString("name");
+
+ if (!MODIFIED_BLOCKS.contains(name)) {
+ return tag;
+ }
+
+ if (OMINOUS_BLOCKS.contains(name)) {
+ NbtMapBuilder builder = tag.getCompound("states").toBuilder();
+ builder.remove("ominous");
+ return tag.toBuilder().putCompound("states", builder.build()).build();
+ }
+
+ String replacement;
+
+ if (NEW_CORAL_BLOCKS.contains(name)) {
+ replacement = "minecraft:coral_block";
+ String coralColor;
+ boolean deadBit = name.startsWith("minecraft:dead_");
+
+ switch(name) {
+ case "minecraft:tube_coral_block", "minecraft:dead_tube_coral_block" -> coralColor = "blue";
+ case "minecraft:brain_coral_block", "minecraft:dead_brain_coral_block" -> coralColor = "pink";
+ case "minecraft:bubble_coral_block", "minecraft:dead_bubble_coral_block" -> coralColor = "purple";
+ case "minecraft:fire_coral_block", "minecraft:dead_fire_coral_block" -> coralColor = "yellow";
+ case "minecraft:horn_coral_block", "minecraft:dead_horn_coral_block" -> coralColor = "red";
+ default -> throw new IllegalStateException("Unexpected value: " + name);
+ }
+
+ NbtMap states = tag.getCompound("states")
+ .toBuilder()
+ .putString("coral_color", coralColor)
+ .putBoolean("dead_bit", deadBit)
+ .build();
+
+ return tag.toBuilder().putString("name", replacement).putCompound("states", states).build();
+ }
+
+ if (NEW_DOUBLE_PLANTS.contains(name)) {
+ replacement = "minecraft:double_plant";
+ String doublePlantType;
+
+ switch(name) {
+ case "minecraft:sunflower" -> doublePlantType = "sunflower";
+ case "minecraft:lilac" -> doublePlantType = "syringa";
+ case "minecraft:tall_grass" -> doublePlantType = "grass";
+ case "minecraft:large_fern" -> doublePlantType = "fern";
+ case "minecraft:rose_bush" -> doublePlantType = "rose";
+ case "minecraft:peony" -> doublePlantType = "paeonia";
+ default -> throw new IllegalStateException("Unexpected value: " + name);
+ }
+
+ NbtMap states = tag.getCompound("states")
+ .toBuilder()
+ .putString("double_plant_type", doublePlantType)
+ .build();
+
+ return tag.toBuilder().putString("name", replacement).putCompound("states", states).build();
+ }
+
+ if (NEW_STONE_BLOCK_SLABS.contains(name)) {
+ replacement = "minecraft:stone_block_slab";
+ String stoneSlabType;
+
+ switch(name) {
+ case "minecraft:smooth_stone_slab" -> stoneSlabType = "smooth_stone";
+ case "minecraft:sandstone_slab" -> stoneSlabType = "sandstone";
+ case "minecraft:petrified_oak_slab" -> stoneSlabType = "wood";
+ case "minecraft:cobblestone_slab" -> stoneSlabType = "cobblestone";
+ case "minecraft:brick_slab" -> stoneSlabType = "brick";
+ case "minecraft:stone_brick_slab" -> stoneSlabType = "stone_brick";
+ case "minecraft:quartz_slab" -> stoneSlabType = "quartz";
+ case "minecraft:nether_brick_slab" -> stoneSlabType = "nether_brick";
+ default -> throw new IllegalStateException("Unexpected value: " + name);
+ }
+
+ NbtMap states = tag.getCompound("states")
+ .toBuilder()
+ .putString("stone_slab_type", stoneSlabType)
+ .build();
+
+ return tag.toBuilder().putString("name", replacement).putCompound("states", states).build();
+ }
+
+ if (NEW_TALLGRASSES.contains(name)) {
+ replacement = "minecraft:tallgrass";
+ String tallGrassType;
+
+ switch(name) {
+ case "minecraft:short_grass" -> tallGrassType = "tall";
+ case "minecraft:fern" -> tallGrassType = "fern";
+ default -> throw new IllegalStateException("Unexpected value: " + name);
+ }
+
+ NbtMap states = tag.getCompound("states")
+ .toBuilder()
+ .putString("tall_grass_type", tallGrassType)
+ .build();
+
+ return tag.toBuilder().putString("name", replacement).putCompound("states", states).build();
+ }
+
+ return tag;
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java
index b2d238ddb..a43df3f52 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java
@@ -53,7 +53,6 @@ import org.geysermc.geyser.level.block.GeyserCustomBlockData;
import org.geysermc.geyser.level.block.GeyserCustomBlockState;
import org.geysermc.geyser.level.block.GeyserGeometryComponent;
import org.geysermc.geyser.level.block.GeyserMaterialInstance;
-import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.mappings.MappingsConfigReader;
import org.geysermc.geyser.registry.type.CustomSkull;
@@ -325,13 +324,11 @@ public class CustomBlockRegistryPopulator {
// meaning of this version is unknown, but it's required for tags to work and should probably be checked periodically
.putInt("molangVersion", 1)
.putList("permutations", NbtType.COMPOUND, permutations)
- .putList("properties", NbtType.COMPOUND, properties);
-
- if (GameProtocol.is1_20_60orHigher(protocolVersion)) {
- propertyTag.putCompound("vanilla_block_data", NbtMap.builder()
+ .putList("properties", NbtType.COMPOUND, properties)
+ .putCompound("vanilla_block_data", NbtMap.builder()
.putInt("block_id", BLOCK_ID.getAndIncrement())
.build());
- }
+
return new BlockPropertyData(customBlock.identifier(), propertyTag.build());
}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java
index 10d87a8a9..a6fa164c1 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomItemRegistryPopulator.java
@@ -44,7 +44,6 @@ import org.geysermc.geyser.item.GeyserCustomMappingData;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.components.WearableSlot;
import org.geysermc.geyser.item.type.Item;
-import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.mappings.MappingsConfigReader;
import org.geysermc.geyser.registry.type.GeyserMappingItem;
import org.geysermc.geyser.registry.type.ItemMapping;
@@ -260,18 +259,11 @@ public class CustomItemRegistryPopulator {
}
private static void setupBasicItemInfo(int maxDamage, int stackSize, boolean displayHandheld, CustomItemData customItemData, NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder, int protocolVersion) {
- NbtMap iconMap;
- if (GameProtocol.is1_20_60orHigher(protocolVersion)) {
- iconMap = NbtMap.builder()
- .putCompound("textures", NbtMap.builder()
- .putString("default", customItemData.icon())
- .build())
- .build();
- } else {
- iconMap = NbtMap.builder()
- .putString("texture", customItemData.icon())
- .build();
- }
+ NbtMap iconMap = NbtMap.builder()
+ .putCompound("textures", NbtMap.builder()
+ .putString("default", customItemData.icon())
+ .build())
+ .build();
itemProperties.putCompound("minecraft:icon", iconMap);
if (customItemData.creativeCategory().isPresent()) {
@@ -427,64 +419,56 @@ public class CustomItemRegistryPopulator {
// Make bows, tridents, and crossbows enchantable
itemProperties.putInt("enchantable_value", 1);
- if (GameProtocol.is1_20_60orHigher(protocolVersion)) {
- componentBuilder.putCompound("minecraft:use_modifiers", NbtMap.builder()
- .putFloat("use_duration", 100F)
- .putFloat("movement_modifier", 0.35F)
- .build());
+ componentBuilder.putCompound("minecraft:use_modifiers", NbtMap.builder()
+ .putFloat("use_duration", 100F)
+ .putFloat("movement_modifier", 0.35F)
+ .build());
- switch (mapping) {
- case "minecraft:bow" -> {
- itemProperties.putString("enchantable_slot", "bow");
- itemProperties.putInt("frame_count", 3);
+ switch (mapping) {
+ case "minecraft:bow" -> {
+ itemProperties.putString("enchantable_slot", "bow");
+ itemProperties.putInt("frame_count", 3);
- componentBuilder.putCompound("minecraft:shooter", NbtMap.builder()
- .putList("ammunition", NbtType.COMPOUND, List.of(
- NbtMap.builder()
- .putCompound("item", NbtMap.builder()
- .putString("name", "minecraft:arrow")
- .build())
- .putBoolean("use_offhand", true)
- .putBoolean("search_inventory", true)
- .build()
- ))
- .putFloat("max_draw_duration", 0f)
- .putBoolean("charge_on_draw", true)
- .putBoolean("scale_power_by_draw_duration", true)
- .build());
- componentBuilder.putInt("minecraft:use_duration", 999);
- }
- case "minecraft:trident" -> {
- itemProperties.putString("enchantable_slot", "trident");
- componentBuilder.putInt("minecraft:use_duration", 999);
- }
- case "minecraft:crossbow" -> {
- itemProperties.putString("enchantable_slot", "crossbow");
- itemProperties.putInt("frame_count", 10);
-
- componentBuilder.putCompound("minecraft:shooter", NbtMap.builder()
- .putList("ammunition", NbtType.COMPOUND, List.of(
- NbtMap.builder()
- .putCompound("item", NbtMap.builder()
- .putString("name", "minecraft:arrow")
- .build())
- .putBoolean("use_offhand", true)
- .putBoolean("search_inventory", true)
- .build()
- ))
- .putFloat("max_draw_duration", 1f)
- .putBoolean("charge_on_draw", true)
- .putBoolean("scale_power_by_draw_duration", true)
- .build());
- componentBuilder.putInt("minecraft:use_duration", 999);
- }
+ componentBuilder.putCompound("minecraft:shooter", NbtMap.builder()
+ .putList("ammunition", NbtType.COMPOUND, List.of(
+ NbtMap.builder()
+ .putCompound("item", NbtMap.builder()
+ .putString("name", "minecraft:arrow")
+ .build())
+ .putBoolean("use_offhand", true)
+ .putBoolean("search_inventory", true)
+ .build()
+ ))
+ .putFloat("max_draw_duration", 0f)
+ .putBoolean("charge_on_draw", true)
+ .putBoolean("scale_power_by_draw_duration", true)
+ .build());
+ componentBuilder.putInt("minecraft:use_duration", 999);
}
- } else {
- // ensure client moves at slow speed while charging (note: this was calculated by hand as the movement modifer value does not seem to scale linearly)
- componentBuilder.putCompound("minecraft:chargeable", NbtMap.builder().putFloat("movement_modifier", 0.35F).build());
+ case "minecraft:trident" -> {
+ itemProperties.putString("enchantable_slot", "trident");
+ componentBuilder.putInt("minecraft:use_duration", 999);
+ }
+ case "minecraft:crossbow" -> {
+ itemProperties.putString("enchantable_slot", "crossbow");
+ itemProperties.putInt("frame_count", 10);
- // keep item enchantable; also works on 1.20.50
- itemProperties.putString("enchantable_slot", mapping.replace("minecraft:", ""));
+ componentBuilder.putCompound("minecraft:shooter", NbtMap.builder()
+ .putList("ammunition", NbtType.COMPOUND, List.of(
+ NbtMap.builder()
+ .putCompound("item", NbtMap.builder()
+ .putString("name", "minecraft:arrow")
+ .build())
+ .putBoolean("use_offhand", true)
+ .putBoolean("search_inventory", true)
+ .build()
+ ))
+ .putFloat("max_draw_duration", 1f)
+ .putBoolean("charge_on_draw", true)
+ .putBoolean("scale_power_by_draw_duration", true)
+ .build());
+ componentBuilder.putInt("minecraft:use_duration", 999);
+ }
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java
index d3a4bed84..8f515c1cb 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java
@@ -38,11 +38,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
-import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622;
-import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630;
-import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649;
-import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662;
+import org.cloudburstmc.nbt.NbtUtils;
import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671;
+import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
@@ -62,7 +60,6 @@ import org.geysermc.geyser.inventory.item.StoredItemMappings;
import org.geysermc.geyser.item.GeyserCustomMappingData;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
-import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.*;
@@ -91,11 +88,8 @@ public class ItemRegistryPopulator {
public static void populate() {
List paletteVersions = new ArrayList<>(3);
- paletteVersions.add(new PaletteVersion("1_20_40", Bedrock_v622.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion630_622::remapItem));
- paletteVersions.add(new PaletteVersion("1_20_50", Bedrock_v630.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion649_630::remapItem));
- paletteVersions.add(new PaletteVersion("1_20_60", Bedrock_v649.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion662_649::remapItem));
- paletteVersions.add(new PaletteVersion("1_20_70", Bedrock_v662.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion671_662::remapItem));
- paletteVersions.add(new PaletteVersion("1_20_80", Bedrock_v671.CODEC.getProtocolVersion()));
+ paletteVersions.add(new PaletteVersion("1_20_80", Bedrock_v671.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion685_671::remapItem));
+ paletteVersions.add(new PaletteVersion("1_21_0", Bedrock_v685.CODEC.getProtocolVersion()));
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
@@ -109,6 +103,13 @@ public class ItemRegistryPopulator {
throw new AssertionError("Unable to load Java runtime item IDs", e);
}
+ NbtMap vanillaComponents;
+ try (InputStream stream = bootstrap.getResourceOrThrow("mappings/item_components.nbt")) {
+ vanillaComponents = (NbtMap) NbtUtils.createGZIPReader(stream, true, true).readTag();
+ } catch (Exception e) {
+ throw new AssertionError("Unable to load Bedrock item components", e);
+ }
+
boolean customItemsAllowed = GeyserImpl.getInstance().getConfig().isAddNonBedrockItems();
// List values here is important compared to HashSet - we need to preserve the order of what's given to us
@@ -538,6 +539,25 @@ public class ItemRegistryPopulator {
}
}
+ for (Map.Entry entry : vanillaComponents.entrySet()) {
+ String id = entry.getKey();
+ ItemDefinition definition = definitions.get(id);
+ if (definition == null) {
+ // Newer item most likely
+ GeyserImpl.getInstance().getLogger().debug(
+ "Skipping vanilla component " + id + " for protocol " + palette.protocolVersion()
+ );
+ continue;
+ }
+
+ NbtMapBuilder root = NbtMap.builder()
+ .putString("name", id)
+ .putInt("id", definition.getRuntimeId())
+ .putCompound("components", (NbtMap) entry.getValue());
+
+ componentItemData.add(new ComponentItemData(id, root.build()));
+ }
+
// Register the item forms of custom blocks
if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) {
for (CustomBlockData customBlock : BlockRegistries.CUSTOM_BLOCKS.get()) {
@@ -602,18 +622,11 @@ public class ItemRegistryPopulator {
NbtMapBuilder componentBuilder = NbtMap.builder();
// Conveniently, as of 1.16.200, the furnace minecart has a texture AND translation string already.
// Not so conveniently, the way to set an icon changed in 1.20.60
- NbtMap iconMap;
- if (GameProtocol.is1_20_60orHigher(protocolVersion)) {
- iconMap = NbtMap.builder()
- .putCompound("textures", NbtMap.builder()
- .putString("default", "minecart_furnace")
- .build())
- .build();
- } else {
- iconMap = NbtMap.builder()
- .putString("texture", "minecart_furnace")
- .build();
- }
+ NbtMap iconMap = NbtMap.builder()
+ .putCompound("textures", NbtMap.builder()
+ .putString("default", "minecart_furnace")
+ .build())
+ .build();
itemProperties.putCompound("minecraft:icon", iconMap);
componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", "item.minecartFurnace.name").build());
diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java
index 928ab8df9..4c6d53518 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java
@@ -35,6 +35,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtUtils;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
+import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.RecipeUnlockingRequirement;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.MultiRecipeData;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapedRecipeData;
@@ -173,7 +174,7 @@ public class RecipeRegistryPopulator {
/* Convert end */
return ShapedRecipeData.shaped(uuid.toString(), shape.get(0).length(), shape.size(),
- inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId, false);
+ inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId, false, RecipeUnlockingRequirement.INVALID);
}
List inputs = new ObjectArrayList<>();
for (JsonNode entry : node.get("inputs")) {
@@ -196,7 +197,7 @@ public class RecipeRegistryPopulator {
inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId);
}
return ShapelessRecipeData.shapeless(uuid.toString(),
- inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId);
+ inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId, RecipeUnlockingRequirement.INVALID);
}
private static ItemData getBedrockItemFromIdentifierJson(ItemMapping mapping, JsonNode itemNode) {
diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java
deleted file mode 100644
index 0196ac22f..000000000
--- a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-
-package org.geysermc.geyser.registry.type;
-
-import lombok.Builder;
-import lombok.Value;
-import org.checkerframework.checker.nullness.qual.NonNull;
-import org.checkerframework.checker.nullness.qual.Nullable;
-import org.geysermc.geyser.level.physics.PistonBehavior;
-import org.geysermc.geyser.util.BlockUtils;
-
-@Builder
-@Value
-public class BlockMapping {
- public static BlockMapping DEFAULT = BlockMapping.builder().javaIdentifier("minecraft:air").pistonBehavior(PistonBehavior.NORMAL).build();
-
- String javaIdentifier;
- /**
- * The block ID shared between all different block states of this block.
- * NOT the runtime ID!
- */
- int javaBlockId;
-
- float hardness;
- boolean canBreakWithHand;
- /**
- * The index of this collision in collision.json
- */
- int collisionIndex;
- @Nullable String pickItem;
-
- @NonNull PistonBehavior pistonBehavior;
- boolean isBlockEntity;
- boolean isNonVanilla;
-
- /**
- * @return the identifier without the additional block states
- */
- public String getCleanJavaIdentifier() {
- return BlockUtils.getCleanIdentifier(javaIdentifier);
- }
-
- /**
- * @return the corresponding Java identifier for this item
- */
- public String getItemIdentifier() {
- if (pickItem != null && !pickItem.equals("minecraft:air")) {
- // Spawners can have air as their pick item which we are not interested in.
- return pickItem;
- }
-
- return getCleanJavaIdentifier();
- }
-
- /**
- * Get the item a Java client would receive when pressing
- * the Pick Block key on a specific Java block state.
- *
- * @return The Java identifier of the item
- */
- public String getPickItem() {
- if (pickItem != null) {
- return pickItem;
- }
-
- return getCleanJavaIdentifier();
- }
-}
diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java
index c76f024af..5c4e835e4 100644
--- a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java
+++ b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java
@@ -35,6 +35,8 @@ import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.common.DefinitionRegistry;
import org.geysermc.geyser.api.block.custom.CustomBlockState;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
import java.util.List;
import java.util.Map;
@@ -50,6 +52,12 @@ public class BlockMappings implements DefinitionRegistry {
GeyserBedrockBlock[] javaToBedrockBlocks;
GeyserBedrockBlock[] javaToVanillaBedrockBlocks;
+ /**
+ * Java block ID -> Bedrock block ID (without minecraft:), IF they are different
+ * While Bedrock is progressing slowly through their flattening, some Bedrock identifiers may differ.
+ */
+ Int2ObjectMap javaToBedrockIdentifiers;
+
Map stateDefinitionMap;
GeyserBedrockBlock[] bedrockRuntimeMap;
int[] remappedVanillaIds;
@@ -58,7 +66,7 @@ public class BlockMappings implements DefinitionRegistry {
BlockDefinition mobSpawnerBlock;
Map itemFrames;
- Map flowerPotBlocks;
+ Map flowerPotBlocks;
Set jigsawStates;
Map structureBlockStates;
@@ -78,6 +86,14 @@ public class BlockMappings implements DefinitionRegistry {
return this.javaToBedrockBlocks[javaState];
}
+ public GeyserBedrockBlock getBedrockBlock(BlockState javaState) {
+ return this.getBedrockBlock(javaState.javaId());
+ }
+
+ public GeyserBedrockBlock getVanillaBedrockBlock(BlockState javaState) {
+ return getVanillaBedrockBlock(javaState.javaId());
+ }
+
public GeyserBedrockBlock getVanillaBedrockBlock(int javaState) {
if (javaState < 0 || javaState >= this.javaToVanillaBedrockBlocks.length) {
return bedrockAir;
diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
index 2b7ec0a97..fc000b95f 100644
--- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
+++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
@@ -28,35 +28,6 @@ package org.geysermc.geyser.session;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.auth.exception.request.RequestException;
import com.github.steveice10.mc.auth.service.MsaAuthenticationService;
-import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
-import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
-import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
-import org.geysermc.mcprotocollib.protocol.data.UnexpectedEncryptionException;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.HandPreference;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction;
-import org.geysermc.mcprotocollib.protocol.data.game.setting.ChatVisibility;
-import org.geysermc.mcprotocollib.protocol.data.game.setting.SkinPart;
-import org.geysermc.mcprotocollib.protocol.data.game.statistic.CustomStatistic;
-import org.geysermc.mcprotocollib.protocol.data.game.statistic.Statistic;
-import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundClientInformationPacket;
-import org.geysermc.mcprotocollib.protocol.packet.handshake.serverbound.ClientIntentionPacket;
-import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket;
-import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatPacket;
-import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
-import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket;
-import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
-import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket;
-import org.geysermc.mcprotocollib.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket;
-import org.geysermc.mcprotocollib.network.BuiltinFlags;
-import org.geysermc.mcprotocollib.network.Session;
-import org.geysermc.mcprotocollib.network.event.session.*;
-import org.geysermc.mcprotocollib.network.packet.Packet;
-import org.geysermc.mcprotocollib.network.tcp.TcpClientSession;
-import org.geysermc.mcprotocollib.network.tcp.TcpSession;
import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@@ -126,8 +97,8 @@ import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.item.type.BlockItem;
import org.geysermc.geyser.level.JavaDimension;
-import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.level.physics.CollisionManager;
import org.geysermc.geyser.network.netty.LocalSession;
import org.geysermc.geyser.registry.Registries;
@@ -145,6 +116,38 @@ import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.LoginEncryptionUtils;
+import org.geysermc.mcprotocollib.network.BuiltinFlags;
+import org.geysermc.mcprotocollib.network.Session;
+import org.geysermc.mcprotocollib.network.event.session.*;
+import org.geysermc.mcprotocollib.network.packet.Packet;
+import org.geysermc.mcprotocollib.network.tcp.TcpClientSession;
+import org.geysermc.mcprotocollib.network.tcp.TcpSession;
+import org.geysermc.mcprotocollib.protocol.ClientListener;
+import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
+import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
+import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
+import org.geysermc.mcprotocollib.protocol.data.UnexpectedEncryptionException;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.HandPreference;
+import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction;
+import org.geysermc.mcprotocollib.protocol.data.game.setting.ChatVisibility;
+import org.geysermc.mcprotocollib.protocol.data.game.setting.SkinPart;
+import org.geysermc.mcprotocollib.protocol.data.game.statistic.CustomStatistic;
+import org.geysermc.mcprotocollib.protocol.data.game.statistic.Statistic;
+import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundClientInformationPacket;
+import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundFinishConfigurationPacket;
+import org.geysermc.mcprotocollib.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket;
+import org.geysermc.mcprotocollib.protocol.packet.handshake.serverbound.ClientIntentionPacket;
+import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket;
+import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatPacket;
+import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
+import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket;
+import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
+import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket;
+import org.geysermc.mcprotocollib.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket;
import java.net.ConnectException;
import java.net.InetSocketAddress;
@@ -253,13 +256,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
*/
private final Map itemFrameCache = new Object2ObjectOpenHashMap<>();
- /**
- * Stores a list of all lectern locations and their block entity tags.
- * See {@link WorldManager#sendLecternData(GeyserSession, int, int, int)}
- * for more information.
- */
- private final @Nullable Set lecternCache;
-
/**
* A list of all players that have a player head on with a custom texture.
* Our workaround for these players is to give them a custom skin and geometry to emulate wearing a custom skull.
@@ -288,7 +284,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
*/
private volatile boolean closed;
- @Setter
private GameMode gameMode = GameMode.SURVIVAL;
/**
@@ -313,22 +308,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
@Setter
private boolean sprinting;
- /**
- * Whether the player is swimming in water.
- * Used to update speed when crawling.
- */
- @Setter
- private boolean swimmingInWater;
-
- /**
- * Tracks the original speed attribute.
- *
- * We need to do this in order to emulate speeds when sneaking under 1.5-blocks-tall areas if the player isn't sneaking,
- * and when crawling.
- */
- @Setter
- private float originalSpeedAttribute;
-
/**
* The dimension of the player.
* As all entities are in the same world, this can be safely applied to all other entities.
@@ -346,7 +325,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
private Vector3i lastBlockPlacePosition;
@Setter
- private String lastBlockPlacedId;
+ private BlockItem lastBlockPlaced;
@Setter
private boolean interacting;
@@ -621,13 +600,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
this.spawned = false;
this.loggedIn = false;
- if (geyser.getWorldManager().shouldExpectLecternHandled(this)) {
- // Unneeded on these platforms
- this.lecternCache = null;
- } else {
- this.lecternCache = new ObjectOpenHashSet<>();
- }
-
if (geyser.getConfig().getEmoteOffhandWorkaround() != EmoteOffhandWorkaroundOption.NO_EMOTES) {
this.emotes = new HashSet<>();
geyser.getSessionManager().getSessions().values().forEach(player -> this.emotes.addAll(player.getEmotes()));
@@ -646,9 +618,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
sentSpawnPacket = true;
syncEntityProperties();
- // Set the hardcoded shield ID to the ID we just defined in StartGamePacket
- // upstream.getSession().getHardcodedBlockingId().set(this.itemMappings.getStoredItems().shield().getBedrockId());
-
if (GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) {
ItemComponentPacket componentPacket = new ItemComponentPacket();
componentPacket.getItems().addAll(itemMappings.getComponentItemData());
@@ -875,6 +844,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
// Start ticking
tickThread = eventLoop.scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS);
+ this.protocol.setUseDefaultListeners(false);
+
TcpSession downstream;
if (geyser.getBootstrap().getSocketAddress() != null) {
// We're going to connect through the JVM and not through TCP
@@ -907,6 +878,25 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
// Let Geyser handle sending the keep alive
downstream.setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false);
}
+ // We'll handle this since we have the registry data on hand
+ downstream.setFlag(MinecraftConstants.SEND_BLANK_KNOWN_PACKS_RESPONSE, false);
+
+ // This isn't a great solution, but... we want to make sure the finish configuration packet cannot be sent
+ // before the KnownPacks packet.
+ this.downstream.getSession().addListener(new ClientListener(ProtocolState.LOGIN, loginEvent.transferring()) {
+ @Override
+ public void packetReceived(Session session, Packet packet) {
+ if (protocol.getState() == ProtocolState.CONFIGURATION) {
+ if (packet instanceof ClientboundFinishConfigurationPacket) {
+ // Prevent
+ GeyserSession.this.ensureInEventLoop(() -> GeyserSession.this.sendDownstreamPacket(new ServerboundFinishConfigurationPacket()));
+ return;
+ }
+ }
+ super.packetReceived(session, packet);
+ }
+ });
+
downstream.addListener(new SessionAdapter() {
@Override
public void packetSending(PacketSendingEvent event) {
@@ -1264,21 +1254,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
this.sneaking = sneaking;
// Update pose and bounding box on our end
- AttributeData speedAttribute;
- if (!sneaking && (speedAttribute = adjustSpeed()) != null) {
- // Update attributes since we're still "sneaking" under a 1.5-block-tall area
- UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
- attributesPacket.setRuntimeEntityId(playerEntity.getGeyserId());
- attributesPacket.setAttributes(Collections.singletonList(speedAttribute));
- sendUpstreamPacket(attributesPacket);
- // the server *should* update our pose once it has returned to normal
- } else {
- if (!flying) {
- // The pose and bounding box should not be updated if the player is flying
- setSneakingPose(sneaking);
- }
- collisionManager.updateScaffoldingFlags(false);
+ if (!flying) {
+ // The pose and bounding box should not be updated if the player is flying
+ setSneakingPose(sneaking);
}
+ collisionManager.updateScaffoldingFlags(false);
playerEntity.updateBedrockMetadata();
@@ -1321,28 +1301,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
}
}
- /**
- * Adjusts speed if the player is crawling.
- *
- * @return not null if attributes should be updated.
- */
- public @Nullable AttributeData adjustSpeed() {
- AttributeData currentPlayerSpeed = playerEntity.getAttributes().get(GeyserAttributeType.MOVEMENT_SPEED);
- if (currentPlayerSpeed != null) {
- if ((pose.equals(Pose.SNEAKING) && !sneaking && collisionManager.mustPlayerSneakHere()) ||
- (!swimmingInWater && playerEntity.getFlag(EntityFlag.SWIMMING) && !collisionManager.isPlayerInWater())) {
- // Either of those conditions means that Bedrock goes zoom when they shouldn't be
- AttributeData speedAttribute = GeyserAttributeType.MOVEMENT_SPEED.getAttribute(originalSpeedAttribute / 3.32f);
- playerEntity.getAttributes().put(GeyserAttributeType.MOVEMENT_SPEED, speedAttribute);
- return speedAttribute;
- } else if (originalSpeedAttribute != currentPlayerSpeed.getValue()) {
- // Speed has reset to normal
- AttributeData speedAttribute = GeyserAttributeType.MOVEMENT_SPEED.getAttribute(originalSpeedAttribute);
- playerEntity.getAttributes().put(GeyserAttributeType.MOVEMENT_SPEED, speedAttribute);
- return speedAttribute;
- }
- }
- return null;
+ public void setGameMode(GameMode newGamemode) {
+ boolean currentlySpectator = this.gameMode == GameMode.SPECTATOR;
+ this.gameMode = newGamemode;
+ this.cameraData.handleGameModeChange(currentlySpectator, newGamemode);
}
/**
@@ -1546,8 +1508,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
startGamePacket.setEnchantmentSeed(0);
startGamePacket.setMultiplayerCorrelationId("");
- startGamePacket.setItemDefinitions(this.itemMappings.getItemDefinitions().values().stream().toList()); // TODO
- // startGamePacket.setBlockPalette(this.blockMappings.getBedrockBlockPalette());
+ startGamePacket.getItemDefinitions().addAll(this.itemMappings.getItemDefinitions().values());
// Needed for custom block mappings and custom skulls system
startGamePacket.getBlockProperties().addAll(this.blockMappings.getBlockProperties());
@@ -1575,8 +1536,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
startGamePacket.setRewindHistorySize(0);
startGamePacket.setServerAuthoritativeBlockBreaking(false);
- // Entity properties for older versions
- startGamePacket.getExperiments().add(new ExperimentData("upcoming_creator_features", true));
+ startGamePacket.setServerId("");
+ startGamePacket.setWorldId("");
+ startGamePacket.setScenarioId("");
upstream.sendPacket(startGamePacket);
}
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/ChunkCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/ChunkCache.java
index e3a9cba89..7b279857a 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/ChunkCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/ChunkCache.java
@@ -25,6 +25,7 @@
package org.geysermc.geyser.session.cache;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
@@ -92,11 +93,11 @@ public class ChunkCache {
DataPalette palette = chunk.sections()[(y - minY) >> 4];
if (palette == null) {
- if (block != BlockStateValues.JAVA_AIR_ID) {
+ if (block != Block.JAVA_AIR_ID) {
// A previously empty chunk, which is no longer empty as a block has been added to it
palette = DataPalette.createForChunk();
// Fixes the chunk assuming that all blocks is the `block` variable we are updating. /shrug
- palette.getPalette().stateToId(BlockStateValues.JAVA_AIR_ID);
+ palette.getPalette().stateToId(Block.JAVA_AIR_ID);
chunk.sections()[(y - minY) >> 4] = palette;
} else {
// Nothing to update
@@ -109,17 +110,17 @@ public class ChunkCache {
public int getBlockAt(int x, int y, int z) {
if (!cache) {
- return BlockStateValues.JAVA_AIR_ID;
+ return Block.JAVA_AIR_ID;
}
GeyserChunk column = this.getChunk(x >> 4, z >> 4);
if (column == null) {
- return BlockStateValues.JAVA_AIR_ID;
+ return Block.JAVA_AIR_ID;
}
if (y < minY || ((y - minY) >> 4) > column.sections().length - 1) {
// Y likely goes above or below the height limit of this world
- return BlockStateValues.JAVA_AIR_ID;
+ return Block.JAVA_AIR_ID;
}
DataPalette chunk = column.sections()[(y - minY) >> 4];
@@ -127,7 +128,7 @@ public class ChunkCache {
return chunk.get(x & 0xF, y & 0xF, z & 0xF);
}
- return BlockStateValues.JAVA_AIR_ID;
+ return Block.JAVA_AIR_ID;
}
public void removeChunk(int chunkX, int chunkZ) {
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java
index 9581df253..fa4503635 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java
@@ -30,6 +30,8 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.experimental.Accessors;
+import org.cloudburstmc.nbt.NbtMap;
+import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.TrimMaterial;
import org.cloudburstmc.protocol.bedrock.data.TrimPattern;
import org.geysermc.geyser.GeyserImpl;
@@ -42,6 +44,7 @@ import org.geysermc.geyser.session.cache.registry.JavaRegistry;
import org.geysermc.geyser.session.cache.registry.SimpleJavaRegistry;
import org.geysermc.geyser.text.TextDecoration;
import org.geysermc.geyser.translator.level.BiomeTranslator;
+import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry;
import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket;
@@ -63,6 +66,7 @@ import java.util.function.ToIntFunction;
@Accessors(fluent = true)
@Getter
public final class RegistryCache {
+ private static final Map> DEFAULTS;
private static final Map>> REGISTRIES = new HashMap<>();
static {
@@ -73,6 +77,24 @@ public final class RegistryCache {
register("worldgen/biome", (cache, array) -> cache.biomeTranslations = array, BiomeTranslator::loadServerBiome);
register("banner_pattern", cache -> cache.bannerPatterns, ($, entry) -> BannerPattern.getByJavaIdentifier(entry.getId()));
register("wolf_variant", cache -> cache.wolfVariants, ($, entry) -> WolfEntity.WolfVariant.getByJavaIdentifier(entry.getId()));
+
+ // Load from MCProtocolLib's classloader
+ NbtMap tag = MinecraftProtocol.loadNetworkCodec();
+ Map> defaults = new HashMap<>();
+ // Don't create a keySet - no need to create the cached object in HashMap if we don't use it again
+ REGISTRIES.forEach((key, $) -> {
+ List rawValues = tag.getCompound(key)
+ .getList("value", NbtType.COMPOUND);
+ Map values = new HashMap<>();
+ for (NbtMap value : rawValues) {
+ String name = value.getString("name");
+ values.put(name, value.getCompound("element"));
+ }
+ // Can make these maps immutable and as efficient as possible after initialization
+ defaults.put(key, Map.copyOf(values));
+ });
+
+ DEFAULTS = Map.copyOf(defaults);
}
@Getter(AccessLevel.NONE)
@@ -116,13 +138,22 @@ public final class RegistryCache {
* @param the class that represents these entries.
*/
private static void register(String registry, Function> localCacheFunction, BiFunction reader) {
- REGISTRIES.put("minecraft:" + registry, (registryCache, entries) -> {
+ String key = "minecraft:" + registry;
+ REGISTRIES.put(key, (registryCache, entries) -> {
+ Map localRegistry = null;
JavaRegistry localCache = localCacheFunction.apply(registryCache);
// Clear each local cache every time a new registry entry is given to us
// (e.g. proxy server switches)
List builder = new ArrayList<>(entries.size());
for (int i = 0; i < entries.size(); i++) {
RegistryEntry entry = entries.get(i);
+ // If the data is null, that's the server telling us we need to use our default values.
+ if (entry.getData() == null) {
+ if (localRegistry == null) { // Lazy initialize
+ localRegistry = DEFAULTS.get(key);
+ }
+ entry = new RegistryEntry(entry.getId(), localRegistry.get(entry.getId()));
+ }
// This is what Geyser wants to keep as a value for this registry.
T cacheEntry = reader.apply(registryCache.session, entry);
builder.add(i, cacheEntry);
@@ -156,4 +187,8 @@ public final class RegistryCache {
localCacheFunction.accept(registryCache, array);
});
}
+
+ public static void init() {
+ // no-op
+ }
}
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java
index 5b208a41f..a40a1156d 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/SkullCache.java
@@ -25,18 +25,20 @@
package org.geysermc.geyser.session.cache;
-import org.checkerframework.checker.nullness.qual.Nullable;
-import org.cloudburstmc.math.vector.Vector3f;
-import org.cloudburstmc.math.vector.Vector3i;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Data;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.cloudburstmc.math.vector.Vector3f;
+import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.block.custom.CustomBlockState;
import org.geysermc.geyser.entity.type.player.SkullPlayerEntity;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.block.type.WallSkullBlock;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.CustomSkull;
import org.geysermc.geyser.session.GeyserSession;
@@ -80,7 +82,7 @@ public class SkullCache {
this.skullRenderDistanceSquared = distance * distance;
}
- public Skull putSkull(Vector3i position, UUID uuid, String texturesProperty, int blockState) {
+ public Skull putSkull(Vector3i position, UUID uuid, String texturesProperty, BlockState blockState) {
Skull skull = skulls.computeIfAbsent(position, Skull::new);
skull.uuid = uuid;
if (!texturesProperty.equals(skull.texturesProperty)) {
@@ -147,7 +149,7 @@ public class SkullCache {
}
}
- public Skull updateSkull(Vector3i position, int blockState) {
+ public Skull updateSkull(Vector3i position, BlockState blockState) {
Skull skull = skulls.get(position);
if (skull != null) {
putSkull(position, skull.uuid, skull.texturesProperty, blockState);
@@ -248,17 +250,14 @@ public class SkullCache {
lastPlayerPosition = null;
}
- private @Nullable BlockDefinition translateCustomSkull(String skinHash, int blockState) {
+ private @Nullable BlockDefinition translateCustomSkull(String skinHash, BlockState blockState) {
CustomSkull customSkull = BlockRegistries.CUSTOM_SKULLS.get(skinHash);
if (customSkull != null) {
- byte floorRotation = BlockStateValues.getSkullRotation(blockState);
CustomBlockState customBlockState;
- if (floorRotation == -1) {
- // Wall skull
- int wallDirection = BlockStateValues.getSkullWallDirections().get(blockState);
- customBlockState = customSkull.getWallBlockState(wallDirection);
+ if (blockState.block() instanceof WallSkullBlock) {
+ customBlockState = customSkull.getWallBlockState(WallSkullBlock.getDegrees(blockState));
} else {
- customBlockState = customSkull.getFloorBlockState(floorRotation);
+ customBlockState = customSkull.getFloorBlockState(blockState.getValue(Properties.ROTATION_16));
}
return session.getBlockMappings().getCustomBlockStateDefinitions().get(customBlockState);
@@ -273,7 +272,7 @@ public class SkullCache {
private String texturesProperty;
private String skinHash;
- private int blockState;
+ private BlockState blockState;
private BlockDefinition blockDefinition;
private SkullPlayerEntity entity;
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
index 38ac32214..95f5c1cc3 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/TagCache.java
@@ -25,15 +25,15 @@
package org.geysermc.geyser.session.cache;
-import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket;
import it.unimi.dsi.fastutil.ints.IntList;
import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item;
-import org.geysermc.geyser.registry.type.BlockMapping;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.BlockTag;
import org.geysermc.geyser.session.cache.tags.ItemTag;
+import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.EnumMap;
@@ -98,10 +98,10 @@ public final class TagCache {
/**
* @return true if the block tag is present and contains this block mapping's Java ID.
*/
- public boolean is(BlockTag tag, BlockMapping mapping) {
+ public boolean is(BlockTag tag, Block block) {
IntList values = this.blocks.get(tag);
if (values != null) {
- return values.contains(mapping.getJavaBlockId());
+ return values.contains(block.javaId());
}
return false;
}
diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java
index c84126608..44ec7a6b9 100644
--- a/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java
+++ b/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java
@@ -180,7 +180,7 @@ public final class WorldCache {
// This block may be out of sync with the server
// In 1.19.0 Java, you can verify this by trying to mine in spawn protection
Vector3i position = entry.getKey();
- ChunkUtils.updateBlockClientSide(session, session.getGeyser().getWorldManager().getBlockAt(session, position), position);
+ ChunkUtils.updateBlockClientSide(session, session.getGeyser().getWorldManager().blockAt(session, position), position);
it.remove();
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java b/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java
deleted file mode 100644
index f139b0bba..000000000
--- a/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-
-package org.geysermc.geyser.text;
-
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-import org.checkerframework.checker.nullness.qual.NonNull;
-import org.checkerframework.checker.nullness.qual.Nullable;
-import org.cloudburstmc.protocol.bedrock.packet.TextPacket;
-import org.geysermc.mcprotocollib.protocol.data.game.chat.BuiltinChatType;
-
-public record ChatTypeEntry(TextPacket.@NonNull Type bedrockChatType, @Nullable TextDecoration textDecoration) {
- private static final ChatTypeEntry CHAT = new ChatTypeEntry(TextPacket.Type.CHAT, null);
- private static final ChatTypeEntry RAW = new ChatTypeEntry(TextPacket.Type.RAW, null);
-
- /**
- * Apply defaults to a map so it isn't empty in the event a chat message is sent before the login packet.
- */
- public static void applyDefaults(Int2ObjectMap chatTypes) {
- // So the proper way to do this, probably, would be to dump the NBT data from vanilla and load it.
- // But, the only way this happens is if a chat message is sent to us before the login packet, which is rare.
- // So we'll just make sure chat ends up in the right place.
- chatTypes.put(BuiltinChatType.CHAT.ordinal(), CHAT);
- chatTypes.put(BuiltinChatType.SAY_COMMAND.ordinal(), RAW);
- chatTypes.put(BuiltinChatType.MSG_COMMAND_INCOMING.ordinal(), RAW);
- chatTypes.put(BuiltinChatType.MSG_COMMAND_OUTGOING.ordinal(), RAW);
- chatTypes.put(BuiltinChatType.TEAM_MSG_COMMAND_INCOMING.ordinal(), RAW);
- chatTypes.put(BuiltinChatType.TEAM_MSG_COMMAND_OUTGOING.ordinal(), RAW);
- chatTypes.put(BuiltinChatType.EMOTE_COMMAND.ordinal(), RAW);
- }
-}
diff --git a/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java b/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java
index c6a58e75e..cfe950409 100644
--- a/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java
+++ b/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java
@@ -148,9 +148,9 @@ public class GeyserLocale {
} catch (IOException ignored) {}
}
} else {
- if (GeyserImpl.getInstance() != null && !validLocalLanguage) {
+ if (!validLocalLanguage) {
// Don't warn on missing locales if a local file has been found
- GeyserImpl.getInstance().getLogger().warning("Missing locale: " + locale);
+ bootstrap.getGeyserLogger().warning("Missing locale: " + locale);
}
}
@@ -162,12 +162,7 @@ public class GeyserLocale {
localeProp.load(stream);
} catch (IOException e) {
String message = "Unable to load custom language override!";
- if (GeyserImpl.getInstance() != null) {
- GeyserImpl.getInstance().getLogger().error(message, e);
- } else {
- System.err.println(message);
- e.printStackTrace();
- }
+ bootstrap.getGeyserLogger().error(message, e);
}
LOCALE_MAPPINGS.putIfAbsent(locale, localeProp);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java
index a2615deb1..2481028a4 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java
@@ -61,7 +61,7 @@ public class BlockCollision {
}
/**
- * Overridden in classes like SnowCollision and GrassPathCollision when correction code needs to be run before the
+ * Overridden in classes like GrassPathCollision when correction code needs to be run before the
* main correction
*/
public void beforeCorrectPosition(int x, int y, int z, BoundingBox playerCollision) {}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/CollisionRemapper.java b/core/src/main/java/org/geysermc/geyser/translator/collision/CollisionRemapper.java
index 6980968ab..fb93a14d5 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/collision/CollisionRemapper.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/collision/CollisionRemapper.java
@@ -37,12 +37,6 @@ public @interface CollisionRemapper {
*/
String regex();
- /**
- * Regex of block state parameters to apply this collision to
- * Defaults to matching any value
- */
- String paramRegex() default ".*";
-
/**
* Signals if a new instance needs to created for every block state
*/
diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/DirtPathCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/DirtPathCollision.java
index dcbad4758..d44187a0c 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/collision/DirtPathCollision.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/collision/DirtPathCollision.java
@@ -26,13 +26,14 @@
package org.geysermc.geyser.translator.collision;
import lombok.EqualsAndHashCode;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.level.physics.CollisionManager;
@EqualsAndHashCode(callSuper = true)
@CollisionRemapper(regex = "^dirt_path$", passDefaultBoxes = true)
public class DirtPathCollision extends BlockCollision {
- public DirtPathCollision(String params, BoundingBox[] defaultBoxes) {
+ public DirtPathCollision(BlockState state, BoundingBox[] defaultBoxes) {
super(defaultBoxes);
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/DoorCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/DoorCollision.java
index b47b187c4..33c85ce07 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/collision/DoorCollision.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/collision/DoorCollision.java
@@ -26,6 +26,8 @@
package org.geysermc.geyser.translator.collision;
import lombok.EqualsAndHashCode;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.session.GeyserSession;
@@ -40,20 +42,18 @@ public class DoorCollision extends BlockCollision {
*/
private int facing;
- public DoorCollision(String params, BoundingBox[] defaultBoxes) {
+ public DoorCollision(BlockState state, BoundingBox[] defaultBoxes) {
super(defaultBoxes);
- if (params.contains("facing=north")) {
- facing = 1;
- } else if (params.contains("facing=east")) {
- facing = 2;
- } else if (params.contains("facing=south")) {
- facing = 3;
- } else if (params.contains("facing=west")) {
- facing = 4;
- }
+ facing = switch (state.getValue(Properties.HORIZONTAL_FACING)) {
+ case NORTH -> 1;
+ case EAST -> 2;
+ case SOUTH -> 3;
+ case WEST -> 4;
+ default -> throw new IllegalStateException();
+ };
// If the door is open it changes direction
- if (params.contains("open=true")) {
+ if (state.getValue(Properties.OPEN)) {
facing = facing % 2 + 1;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/GlassPaneAndIronBarsCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/GlassPaneAndIronBarsCollision.java
index 14439645a..35874348c 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/collision/GlassPaneAndIronBarsCollision.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/collision/GlassPaneAndIronBarsCollision.java
@@ -26,6 +26,8 @@
package org.geysermc.geyser.translator.collision;
import lombok.EqualsAndHashCode;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.session.GeyserSession;
@@ -44,24 +46,23 @@ public class GlassPaneAndIronBarsCollision extends BlockCollision {
*/
private int facing;
- public GlassPaneAndIronBarsCollision(String params, BoundingBox[] defaultBoxes) {
+ public GlassPaneAndIronBarsCollision(BlockState state, BoundingBox[] defaultBoxes) {
super(defaultBoxes);
- //east=true,north=true,south=true,west=true
- if (params.contains("north=true") && params.contains("east=true")) {
+ if (state.getValue(Properties.NORTH) && state.getValue(Properties.EAST)) {
facing = 5;
- } else if (params.contains("east=true") && params.contains("south=true")) {
+ } else if (state.getValue(Properties.EAST) && state.getValue(Properties.SOUTH)) {
facing = 6;
- } else if (params.contains("south=true") && params.contains("west=true")) {
+ } else if (state.getValue(Properties.SOUTH) && state.getValue(Properties.WEST)) {
facing = 7;
- } else if (params.contains("west=true") && params.contains("north=true")) {
+ } else if (state.getValue(Properties.WEST) && state.getValue(Properties.NORTH)) {
facing = 8;
- } else if (params.contains("north=true")) {
+ } else if (state.getValue(Properties.NORTH)) {
facing = 1;
- } else if (params.contains("east=true")) {
+ } else if (state.getValue(Properties.EAST)) {
facing = 2;
- } else if (params.contains("south=true")) {
+ } else if (state.getValue(Properties.SOUTH)) {
facing = 3;
- } else if (params.contains("west=true")) {
+ } else if (state.getValue(Properties.WEST)) {
facing = 4;
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/ScaffoldingCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/ScaffoldingCollision.java
index dfbd1c8b8..7449987c6 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/collision/ScaffoldingCollision.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/collision/ScaffoldingCollision.java
@@ -26,6 +26,7 @@
package org.geysermc.geyser.translator.collision;
import lombok.EqualsAndHashCode;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.session.GeyserSession;
@@ -35,7 +36,7 @@ import org.geysermc.geyser.session.GeyserSession;
@EqualsAndHashCode(callSuper = true)
@CollisionRemapper(regex = "^scaffolding$", usesParams = true, passDefaultBoxes = true)
public class ScaffoldingCollision extends BlockCollision {
- public ScaffoldingCollision(String params, BoundingBox[] defaultBoxes) {
+ public ScaffoldingCollision(BlockState state, BoundingBox[] defaultBoxes) {
super(defaultBoxes);
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java
deleted file mode 100644
index fb83e357d..000000000
--- a/core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-
-package org.geysermc.geyser.translator.collision;
-
-import lombok.EqualsAndHashCode;
-import org.geysermc.geyser.level.physics.BoundingBox;
-import org.geysermc.geyser.session.GeyserSession;
-
-@EqualsAndHashCode(callSuper = true)
-@CollisionRemapper(regex = "^snow$", passDefaultBoxes = true, usesParams = true)
-public class SnowCollision extends BlockCollision {
- private final int layers;
-
- public SnowCollision(String params, BoundingBox[] defaultBoxes) {
- super(defaultBoxes);
- int layerCharIndex = params.indexOf("=") + 1;
- layers = Integer.parseInt(params.substring(layerCharIndex, layerCharIndex + 1));
-
- pushUpTolerance = 0.125;
- }
-
- // Needs to run before the main correction code or it can move the player into blocks
- // This is counteracted by the main collision code pushing them out
- @Override
- public void beforeCorrectPosition(int x, int y, int z, BoundingBox playerCollision) {
- // In Bedrock, snow layers round down to half blocks but you can't sink into them at all
- // This means the collision each half block reaches above where it should be on Java so the player has to be
- // pushed down
- if (layers == 4 || layers == 8) {
- double playerMinY = playerCollision.getMiddleY() - (playerCollision.getSizeY() / 2);
- double boxMaxY = (boundingBoxes[0].getMiddleY() + y) + (boundingBoxes[0].getSizeY() / 2);
- // If the player is in the buggy area, push them down
- if (playerMinY > boxMaxY &&
- playerMinY <= (boxMaxY + 0.125)) {
- playerCollision.translate(0, boxMaxY - playerMinY, 0);
- }
- }
- }
-
- @Override
- public boolean correctPosition(GeyserSession session, int x, int y, int z, BoundingBox playerCollision) {
- if (layers == 1) {
- // 1 layer of snow does not have collision
- return true;
- }
- // Hack to prevent false positives
- playerCollision.setSizeX(playerCollision.getSizeX() - 0.0001);
- playerCollision.setSizeY(playerCollision.getSizeY() - 0.0001);
- playerCollision.setSizeZ(playerCollision.getSizeZ() - 0.0001);
-
- if (this.checkIntersection(x, y, z, playerCollision)) {
- double playerMinY = playerCollision.getMiddleY() - (playerCollision.getSizeY() / 2);
- double boxMaxY = (boundingBoxes[0].getMiddleY() + y) + (boundingBoxes[0].getSizeY() / 2);
- // If the player actually can't step onto it (they can step onto it from other snow layers)
- if ((boxMaxY - playerMinY) > 0.5) {
- // Cancel the movement
- return false;
- }
- }
-
- playerCollision.setSizeX(playerCollision.getSizeX() + 0.0001);
- playerCollision.setSizeY(playerCollision.getSizeY() + 0.0001);
- playerCollision.setSizeZ(playerCollision.getSizeZ() + 0.0001);
- return super.correctPosition(session, x, y, z, playerCollision);
- }
-}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/SolidCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/SolidCollision.java
index 822202ff2..51d1038c0 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/collision/SolidCollision.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/collision/SolidCollision.java
@@ -26,12 +26,13 @@
package org.geysermc.geyser.translator.collision;
import lombok.EqualsAndHashCode;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.BoundingBox;
@EqualsAndHashCode(callSuper = true)
@CollisionRemapper(regex = "shulker_box$") // These have no collision in the mappings as it depends on the NBT data
public class SolidCollision extends BlockCollision {
- public SolidCollision(String params) {
+ public SolidCollision(BlockState state) {
super(new BoundingBox[] {
new BoundingBox(0.5, 0.5, 0.5, 1, 1, 1)
});
diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/TrapdoorCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/TrapdoorCollision.java
index 836c05711..909761166 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/collision/TrapdoorCollision.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/collision/TrapdoorCollision.java
@@ -26,42 +26,27 @@
package org.geysermc.geyser.translator.collision;
import lombok.EqualsAndHashCode;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.level.physics.CollisionManager;
+import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.session.GeyserSession;
@EqualsAndHashCode(callSuper = true)
@CollisionRemapper(regex = "_trapdoor$", usesParams = true, passDefaultBoxes = true)
public class TrapdoorCollision extends BlockCollision {
- /**
- * 1 = north
- * 2 = east
- * 3 = south
- * 4 = west
- * 5 = up
- * 6 = down
- */
- private int facing;
+ private final Direction facing;
- public TrapdoorCollision(String params, BoundingBox[] defaultBoxes) {
+ public TrapdoorCollision(BlockState state, BoundingBox[] defaultBoxes) {
super(defaultBoxes);
- if (params.contains("open=true")) {
- if (params.contains("facing=north")) {
- facing = 1;
- } else if (params.contains("facing=east")) {
- facing = 2;
- } else if (params.contains("facing=south")) {
- facing = 3;
- } else if (params.contains("facing=west")) {
- facing = 4;
- }
+ if (state.getValue(Properties.OPEN)) {
+ facing = state.getValue(Properties.HORIZONTAL_FACING);
} else {
- if (params.contains("half=bottom")) {
- // Up
- facing = 5;
+ if (state.getValue(Properties.HALF).equals("bottom")) {
+ facing = Direction.UP;
} else {
- // Down
- facing = 6;
+ facing = Direction.DOWN;
}
}
}
@@ -72,22 +57,22 @@ public class TrapdoorCollision extends BlockCollision {
// Check for door bug (doors are 0.1875 blocks thick on Java but 0.1825 blocks thick on Bedrock)
if (this.checkIntersection(x, y, z, playerCollision)) {
switch (facing) {
- case 1: // North
+ case NORTH:
playerCollision.setMiddleZ(z + 0.5125);
break;
- case 2: // East
+ case EAST:
playerCollision.setMiddleX(x + 0.5125);
break;
- case 3: // South
+ case SOUTH:
playerCollision.setMiddleZ(z + 0.4875);
break;
- case 4: // West
+ case WEST:
playerCollision.setMiddleX(x + 0.4875);
break;
- case 5:
+ case UP:
// Up-facing trapdoors are handled by the step-up check
break;
- case 6: // Down
+ case DOWN:
// (top y of trap door) - (trap door thickness) = top y of player
playerCollision.setMiddleY(y + 1 - (3.0 / 16.0) - playerCollision.getSizeY() / 2.0 - CollisionManager.COLLISION_TOLERANCE);
break;
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java
index ac6e9870e..4476391c8 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java
@@ -30,6 +30,8 @@ import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.holder.BlockInventoryHolder;
import org.geysermc.geyser.inventory.holder.InventoryHolder;
import org.geysermc.geyser.inventory.updater.InventoryUpdater;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
/**
@@ -39,17 +41,25 @@ public abstract class AbstractBlockInventoryTranslator extends BaseInventoryTran
private final InventoryHolder holder;
private final InventoryUpdater updater;
+ /**
+ * @param javaBlock a Java block that is used as a temporary block
+ */
+ public AbstractBlockInventoryTranslator(int size, Block javaBlock, ContainerType containerType, InventoryUpdater updater,
+ Block... additionalValidBlocks) {
+ this(size, javaBlock.defaultBlockState(), containerType, updater, additionalValidBlocks);
+ }
+
/**
* @param size the amount of slots that the inventory adds alongside the base inventory slots
- * @param javaBlockIdentifier a Java block identifier that is used as a temporary block
+ * @param javaBlockState a Java block state that is used as a temporary block
* @param containerType the container type of this inventory
* @param updater updater
- * @param additionalValidBlocks any other block identifiers that can safely use this inventory without a fake block
+ * @param additionalValidBlocks any other blocks that can safely use this inventory without a fake block
*/
- public AbstractBlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater,
- String... additionalValidBlocks) {
+ public AbstractBlockInventoryTranslator(int size, BlockState javaBlockState, ContainerType containerType, InventoryUpdater updater,
+ Block... additionalValidBlocks) {
super(size);
- this.holder = new BlockInventoryHolder(javaBlockIdentifier, containerType, additionalValidBlocks);
+ this.holder = new BlockInventoryHolder(javaBlockState, containerType, additionalValidBlocks);
this.updater = updater;
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/AnvilInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/AnvilInventoryTranslator.java
index 2da51a0eb..40ee28362 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/AnvilInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/AnvilInventoryTranslator.java
@@ -37,6 +37,7 @@ import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.updater.AnvilInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
@@ -44,8 +45,8 @@ import java.util.Objects;
public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator {
public AnvilInventoryTranslator() {
- super(3, "minecraft:anvil[facing=north]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ANVIL, AnvilInventoryUpdater.INSTANCE,
- "minecraft:chipped_anvil", "minecraft:damaged_anvil");
+ super(3, Blocks.ANVIL, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ANVIL, AnvilInventoryUpdater.INSTANCE,
+ Blocks.CHIPPED_ANVIL, Blocks.DAMAGED_ANVIL);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java
index 9aeeff007..ceae1b640 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/BeaconInventoryTranslator.java
@@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.inventory;
import it.unimi.dsi.fastutil.ints.IntSets;
import org.cloudburstmc.math.vector.Vector3i;
-import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
@@ -43,7 +42,9 @@ import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.holder.BlockInventoryHolder;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
import org.geysermc.geyser.util.InventoryUtils;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetBeaconPacket;
@@ -52,7 +53,7 @@ import java.util.OptionalInt;
public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator {
public BeaconInventoryTranslator() {
- super(1, new BlockInventoryHolder("minecraft:beacon", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.BEACON) {
+ super(1, new BlockInventoryHolder(Blocks.BEACON, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.BEACON) {
@Override
protected boolean checkInteractionPosition(GeyserSession session) {
// Since we can't fall back to a virtual inventory, let's make opening one easier
@@ -89,12 +90,8 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator
// Send a block entity data packet update to the fake beacon inventory
Vector3i position = inventory.getHolderPosition();
- NbtMapBuilder builder = NbtMap.builder()
- .putInt("x", position.getX())
- .putInt("y", position.getY())
- .putInt("z", position.getZ())
+ NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("Beacon", position)
.putString("CustomName", inventory.getTitle())
- .putString("id", "Beacon")
.putInt("primary", beaconContainer.getPrimaryId())
.putInt("secondary", beaconContainer.getSecondaryId());
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/BrewingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/BrewingInventoryTranslator.java
index a2c45384d..e425342f3 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/BrewingInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/BrewingInventoryTranslator.java
@@ -32,11 +32,16 @@ import org.cloudburstmc.protocol.bedrock.packet.ContainerSetDataPacket;
import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
import org.geysermc.geyser.session.GeyserSession;
public class BrewingInventoryTranslator extends AbstractBlockInventoryTranslator {
public BrewingInventoryTranslator() {
- super(5, "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", ContainerType.BREWING_STAND, ContainerInventoryUpdater.INSTANCE);
+ super(5, Blocks.BREWING_STAND.defaultBlockState()
+ .withValue(Properties.HAS_BOTTLE_0, false)
+ .withValue(Properties.HAS_BOTTLE_1, false)
+ .withValue(Properties.HAS_BOTTLE_2, false), ContainerType.BREWING_STAND, ContainerInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java
index a115bd953..b0914e5dd 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/CartographyInventoryTranslator.java
@@ -30,12 +30,13 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemSt
import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
public class CartographyInventoryTranslator extends AbstractBlockInventoryTranslator {
public CartographyInventoryTranslator() {
- super(3, "minecraft:cartography_table", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CARTOGRAPHY, UIInventoryUpdater.INSTANCE);
+ super(3, Blocks.CARTOGRAPHY_TABLE, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CARTOGRAPHY, UIInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java
index 2a2f5beb5..8b0a0ac44 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/CrafterInventoryTranslator.java
@@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.updater.CrafterInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.BlockEntityUtils;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
@@ -53,7 +54,7 @@ public class CrafterInventoryTranslator extends AbstractBlockInventoryTranslator
private static final int TRIGGERED = 1; // triggered value
public CrafterInventoryTranslator() {
- super(10, "minecraft:crafter", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CRAFTER, CrafterInventoryUpdater.INSTANCE);
+ super(10, Blocks.CRAFTER, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CRAFTER, CrafterInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java
index 521db494a..4a0f1d7d9 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java
@@ -31,10 +31,11 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemSt
import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.SlotType;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
public class CraftingInventoryTranslator extends AbstractBlockInventoryTranslator {
public CraftingInventoryTranslator() {
- super(10, "minecraft:crafting_table", ContainerType.WORKBENCH, UIInventoryUpdater.INSTANCE);
+ super(10, Blocks.CRAFTING_TABLE, ContainerType.WORKBENCH, UIInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java
index 8fee2a391..e1407346a 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/EnchantingInventoryTranslator.java
@@ -38,6 +38,7 @@ import org.cloudburstmc.protocol.bedrock.packet.PlayerEnchantOptionsPacket;
import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
@@ -47,7 +48,7 @@ import java.util.Locale;
public class EnchantingInventoryTranslator extends AbstractBlockInventoryTranslator {
public EnchantingInventoryTranslator() {
- super(2, "minecraft:enchanting_table", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ENCHANTMENT, UIInventoryUpdater.INSTANCE);
+ super(2, Blocks.ENCHANTING_TABLE, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ENCHANTMENT, UIInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/Generic3X3InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/Generic3X3InventoryTranslator.java
index 2a80161c0..80040e375 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/Generic3X3InventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/Generic3X3InventoryTranslator.java
@@ -32,6 +32,7 @@ import org.geysermc.geyser.inventory.Generic3X3Container;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
@@ -40,8 +41,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
*/
public class Generic3X3InventoryTranslator extends AbstractBlockInventoryTranslator {
public Generic3X3InventoryTranslator() {
- super(9, "minecraft:dispenser[facing=north,triggered=false]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.DISPENSER, ContainerInventoryUpdater.INSTANCE,
- "minecraft:dropper");
+ super(9, Blocks.DISPENSER, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.DISPENSER, ContainerInventoryUpdater.INSTANCE,
+ Blocks.DROPPER);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/GrindstoneInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/GrindstoneInventoryTranslator.java
index a32b97b70..5344d27cb 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/GrindstoneInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/GrindstoneInventoryTranslator.java
@@ -30,10 +30,11 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
public class GrindstoneInventoryTranslator extends AbstractBlockInventoryTranslator {
public GrindstoneInventoryTranslator() {
- super(3, "minecraft:grindstone[face=floor,facing=north]", ContainerType.GRINDSTONE, UIInventoryUpdater.INSTANCE);
+ super(3, Blocks.GRINDSTONE, ContainerType.GRINDSTONE, UIInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/HopperInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/HopperInventoryTranslator.java
index dab1ee972..fdcd7bf57 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/HopperInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/HopperInventoryTranslator.java
@@ -29,13 +29,14 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
/**
* Implemented on top of any block that does not have special properties implemented
*/
public class HopperInventoryTranslator extends AbstractBlockInventoryTranslator {
public HopperInventoryTranslator() {
- super(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, ContainerInventoryUpdater.INSTANCE);
+ super(5, Blocks.HOPPER, ContainerType.HOPPER, ContainerInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java
index f3bbc9b87..3b33f5909 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LecternInventoryTranslator.java
@@ -28,13 +28,18 @@ package org.geysermc.geyser.translator.inventory;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.erosion.util.LecternUtils;
import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.inventory.*;
+import org.geysermc.geyser.inventory.Container;
+import org.geysermc.geyser.inventory.GeyserItemStack;
+import org.geysermc.geyser.inventory.Inventory;
+import org.geysermc.geyser.inventory.LecternContainer;
+import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
-import org.geysermc.geyser.network.GameProtocol;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.LecternBlock;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.BlockEntityUtils;
import org.geysermc.geyser.util.InventoryUtils;
@@ -43,9 +48,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen
import org.geysermc.mcprotocollib.protocol.data.game.item.component.WritableBookContent;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.WrittenBookContent;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
-import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket;
-
-import java.util.Collections;
public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator {
@@ -56,7 +58,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
private boolean initialized = false;
public LecternInventoryTranslator() {
- super(1, "minecraft:lectern[facing=north,has_book=true,powered=true]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.LECTERN , ContainerInventoryUpdater.INSTANCE);
+ super(1, Blocks.LECTERN, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.LECTERN , ContainerInventoryUpdater.INSTANCE);
}
@Override
@@ -96,7 +98,10 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
// Now: Restore the lectern, if it actually exists
if (lecternContainer.isUsingRealBlock()) {
- GeyserImpl.getInstance().getWorldManager().sendLecternData(session, position.getX(), position.getY(), position.getZ());
+ boolean hasBook = session.getGeyser().getWorldManager().blockAt(session, position).getValue(Properties.HAS_BOOK, false);
+
+ NbtMap map = LecternBlock.getBaseLecternTag(position, hasBook);
+ BlockEntityUtils.updateBlockEntity(session, map, position);
}
}
@@ -149,14 +154,8 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
session.setDroppingLecternBook(false);
InventoryUtils.closeInventory(session, inventory.getJavaId(), false);
} else if (lecternContainer.getBlockEntityTag() == null) {
- Vector3i position = lecternContainer.isUsingRealBlock() ? session.getLastInteractionBlockPosition() : inventory.getHolderPosition();
-
- // If shouldExpectLecternHandled returns true, this is already handled for us
- // shouldRefresh means that we should boot out the client on our side because their lectern GUI isn't updated yet
- // TODO: yeet after 1.20.60 is minimum supported version
- boolean shouldRefresh = !session.getGeyser().getWorldManager().shouldExpectLecternHandled(session)
- && !session.getLecternCache().contains(position)
- && !GameProtocol.is1_20_60orHigher(session.getUpstream().getProtocolVersion());
+ Vector3i position = lecternContainer.isUsingRealBlock() ?
+ session.getLastInteractionBlockPosition() : inventory.getHolderPosition();
NbtMap blockEntityTag;
if (book.getComponents() != null) {
@@ -172,7 +171,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
}
ItemData itemData = book.getItemData(session);
- NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(position.getX(), position.getY(), position.getZ(), pages);
+ NbtMapBuilder lecternTag = LecternBlock.getBaseLecternTag(position, pages);
lecternTag.putCompound("book", NbtMap.builder()
.putByte("Count", (byte) itemData.getCount())
.putShort("Damage", (short) 0)
@@ -183,19 +182,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
blockEntityTag = lecternTag.build();
} else {
// There is *a* book here, but... no NBT.
- NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(position.getX(), position.getY(), position.getZ(), 1);
- NbtMapBuilder bookTag = NbtMap.builder()
- .putByte("Count", (byte) 1)
- .putShort("Damage", (short) 0)
- .putString("Name", "minecraft:writable_book")
- .putCompound("tag", NbtMap.builder().putList("pages", NbtType.COMPOUND, Collections.singletonList(
- NbtMap.builder()
- .putString("photoname", "")
- .putString("text", "")
- .build()
- )).build());
-
- blockEntityTag = lecternTag.putCompound("book", bookTag.build()).build();
+ blockEntityTag = LecternBlock.getBaseLecternTag(position, true);
}
// Even with serverside access to lecterns, we don't easily know which lectern this is, so we need to rebuild
@@ -204,16 +191,6 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
lecternContainer.setPosition(position);
BlockEntityUtils.updateBlockEntity(session, blockEntityTag, position);
-
- if (shouldRefresh) {
- // the lectern cache doesn't always exist; only when we must refresh
- session.getLecternCache().add(position);
-
- // Close the window - we will reopen it once the client has this data synced
- ServerboundContainerClosePacket closeWindowPacket = new ServerboundContainerClosePacket(lecternContainer.getJavaId());
- session.sendDownstreamGamePacket(closeWindowPacket);
- InventoryUtils.closeInventory(session, inventory.getJavaId(), false);
- }
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java
index e8571c8fb..0694e2ac6 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/LoomInventoryTranslator.java
@@ -45,6 +45,7 @@ import org.geysermc.geyser.inventory.SlotType;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
import org.geysermc.geyser.item.type.BannerItem;
import org.geysermc.geyser.item.type.DyeItem;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
@@ -101,7 +102,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
}
public LoomInventoryTranslator() {
- super(4, "minecraft:loom[facing=north]", ContainerType.LOOM, UIInventoryUpdater.INSTANCE);
+ super(4, Blocks.LOOM, ContainerType.LOOM, UIInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java
index 201c900d6..21fe9ca21 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/OldSmithingTableTranslator.java
@@ -37,6 +37,7 @@ import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InventoryUtils;
@@ -53,7 +54,7 @@ public class OldSmithingTableTranslator extends AbstractBlockInventoryTranslator
private static final IntFunction UPGRADE_TEMPLATE = InventoryUtils.getUpgradeTemplate();
private OldSmithingTableTranslator() {
- super(3, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE);
+ super(3, Blocks.SMITHING_TABLE, ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java
index 36752e582..18d6a22eb 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/PlayerInventoryTranslator.java
@@ -550,6 +550,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
ContainerClosePacket packet = new ContainerClosePacket();
packet.setServerInitiated(true);
packet.setId((byte) ContainerId.INVENTORY);
+ packet.setType(org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.INVENTORY);
session.sendUpstreamPacket(packet);
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java
index f9879499a..464bf07f7 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/ShulkerInventoryTranslator.java
@@ -35,6 +35,10 @@ import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.holder.BlockInventoryHolder;
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
@@ -42,16 +46,17 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
public class ShulkerInventoryTranslator extends AbstractBlockInventoryTranslator {
public ShulkerInventoryTranslator() {
- super(27, new BlockInventoryHolder("minecraft:shulker_box[facing=north]", ContainerType.CONTAINER) {
+ // Ensure that the shulker box default state won't be trying to open in a state facing the player
+ super(27, new BlockInventoryHolder(Blocks.SHULKER_BOX.defaultBlockState().withValue(Properties.FACING, Direction.NORTH), ContainerType.CONTAINER) {
private final BlockEntityTranslator shulkerBoxTranslator = Registries.BLOCK_ENTITIES.get(BlockEntityType.SHULKER_BOX);
@Override
- protected boolean isValidBlock(String[] javaBlockString) {
- return javaBlockString[0].contains("shulker_box");
+ protected boolean isValidBlock(BlockState blockState) {
+ return blockState.block().javaIdentifier().value().contains("shulker_box"); // TODO ew
}
@Override
- protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, int javaBlockState) {
+ protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, BlockState javaBlockState) {
NbtMapBuilder tag = NbtMap.builder()
.putInt("x", position.getX())
.putInt("y", position.getY())
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/SmithingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/SmithingInventoryTranslator.java
index 730e4a451..c68347fd3 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/SmithingInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/SmithingInventoryTranslator.java
@@ -30,10 +30,11 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
public class SmithingInventoryTranslator extends AbstractBlockInventoryTranslator {
public SmithingInventoryTranslator() {
- super(4, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE);
+ super(4, Blocks.SMITHING_TABLE, ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java
index 54f2f447b..b977ee1a1 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/StonecutterInventoryTranslator.java
@@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemS
import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
+import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
@@ -42,7 +43,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.S
public class StonecutterInventoryTranslator extends AbstractBlockInventoryTranslator {
public StonecutterInventoryTranslator() {
- super(2, "minecraft:stonecutter[facing=north]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.STONECUTTER, UIInventoryUpdater.INSTANCE);
+ super(2, Blocks.STONECUTTER, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.STONECUTTER, UIInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java
index 498bd418b..856cc1876 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java
@@ -36,11 +36,14 @@ import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.geyser.inventory.Container;
import org.geysermc.geyser.inventory.Inventory;
-import org.geysermc.geyser.level.block.BlockStateValues;
-import org.geysermc.geyser.level.block.DoubleChestValue;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.ChestType;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
import org.geysermc.geyser.translator.level.block.entity.DoubleChestBlockEntityTranslator;
import org.geysermc.geyser.util.InventoryUtils;
@@ -49,31 +52,27 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
public DoubleChestInventoryTranslator(int size) {
super(size, 54);
- this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt("minecraft:chest[facing=north,type=single,waterlogged=false]");
+ this.defaultJavaBlockState = Blocks.CHEST.defaultBlockState()
+ .withValue(Properties.HORIZONTAL_FACING, Direction.NORTH)
+ .withValue(Properties.CHEST_TYPE, ChestType.SINGLE)
+ .javaId();
}
@Override
public boolean prepareInventory(GeyserSession session, Inventory inventory) {
// See BlockInventoryHolder - same concept there except we're also dealing with a specific block state
if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) {
- int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition());
- if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(javaBlockId)) {
- String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.DEFAULT).getJavaIdentifier().split("\\[");
- if (javaBlockString.length > 1 && (javaBlockString[0].equals("minecraft:chest") || javaBlockString[0].equals("minecraft:trapped_chest"))
- && !javaBlockString[1].contains("type=single")) {
+ BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getLastInteractionBlockPosition());
+ if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(state.javaId())) {
+ if ((state.block() == Blocks.CHEST || state.block() == Blocks.TRAPPED_CHEST)
+ && state.getValue(Properties.CHEST_TYPE) != ChestType.SINGLE) {
inventory.setHolderPosition(session.getLastInteractionBlockPosition());
- ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]);
+ ((Container) inventory).setUsingRealBlock(true, state.block());
- NbtMapBuilder tag = NbtMap.builder()
- .putString("id", "Chest")
- .putInt("x", session.getLastInteractionBlockPosition().getX())
- .putInt("y", session.getLastInteractionBlockPosition().getY())
- .putInt("z", session.getLastInteractionBlockPosition().getZ())
- .putString("CustomName", inventory.getTitle())
- .putString("id", "Chest");
+ NbtMapBuilder tag = BlockEntityTranslator.getConstantBedrockTag("Chest", session.getLastInteractionBlockPosition())
+ .putString("CustomName", inventory.getTitle());
- DoubleChestValue chestValue = BlockStateValues.getDoubleChestValues().get(javaBlockId);
- DoubleChestBlockEntityTranslator.translateChestValue(tag, chestValue,
+ DoubleChestBlockEntityTranslator.translateChestValue(tag, state,
session.getLastInteractionBlockPosition().getX(), session.getLastInteractionBlockPosition().getZ());
BlockEntityDataPacket dataPacket = new BlockEntityDataPacket();
@@ -101,11 +100,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
session.sendUpstreamPacket(blockPacket);
- NbtMap tag = NbtMap.builder()
- .putString("id", "Chest")
- .putInt("x", position.getX())
- .putInt("y", position.getY())
- .putInt("z", position.getZ())
+ NbtMap tag = BlockEntityTranslator.getConstantBedrockTag("Chest", position)
.putInt("pairx", pairPosition.getX())
.putInt("pairz", pairPosition.getZ())
.putString("CustomName", inventory.getTitle()).build();
@@ -157,6 +152,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
ContainerClosePacket packet = new ContainerClosePacket();
packet.setId((byte) inventory.getBedrockId());
packet.setServerInitiated(true);
+ packet.setType(ContainerType.MINECART_CHEST);
session.sendUpstreamPacket(packet);
return;
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java
index d09e7e990..264b2eb29 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java
@@ -29,24 +29,29 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.holder.BlockInventoryHolder;
import org.geysermc.geyser.inventory.holder.InventoryHolder;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.ChestType;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
public class SingleChestInventoryTranslator extends ChestInventoryTranslator {
private final InventoryHolder holder;
+ // TODO add barrel???
public SingleChestInventoryTranslator(int size) {
super(size, 27);
- this.holder = new BlockInventoryHolder("minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER,
- "minecraft:ender_chest", "minecraft:trapped_chest") {
+ this.holder = new BlockInventoryHolder(Blocks.CHEST.defaultBlockState().withValue(Properties.CHEST_TYPE, ChestType.SINGLE), ContainerType.CONTAINER,
+ Blocks.ENDER_CHEST, Blocks.TRAPPED_CHEST) {
@Override
- protected boolean isValidBlock(String[] javaBlockString) {
- if (javaBlockString[0].equals("minecraft:ender_chest")) {
+ protected boolean isValidBlock(BlockState blockState) {
+ if (blockState.is(Blocks.ENDER_CHEST)) {
// Can't have double ender chests
return true;
}
// Add provision to ensure this isn't a double chest
- return super.isValidBlock(javaBlockString) && (javaBlockString.length > 1 && javaBlockString[1].contains("type=single"));
+ return super.isValidBlock(blockState) && blockState.getValue(Properties.CHEST_TYPE) == ChestType.SINGLE;
}
};
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/AbstractFurnaceInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/AbstractFurnaceInventoryTranslator.java
index 6cda03a19..8991ef787 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/AbstractFurnaceInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/AbstractFurnaceInventoryTranslator.java
@@ -32,12 +32,14 @@ import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.SlotType;
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.AbstractBlockInventoryTranslator;
public abstract class AbstractFurnaceInventoryTranslator extends AbstractBlockInventoryTranslator {
- AbstractFurnaceInventoryTranslator(String javaBlockIdentifier, ContainerType containerType) {
- super(3, javaBlockIdentifier, containerType, ContainerInventoryUpdater.INSTANCE);
+ AbstractFurnaceInventoryTranslator(Block javaBlock, ContainerType containerType) {
+ super(3, javaBlock.defaultBlockState().withValue(Properties.LIT, false), containerType, ContainerInventoryUpdater.INSTANCE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/BlastFurnaceInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/BlastFurnaceInventoryTranslator.java
index 0b6e0c674..185cafc51 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/BlastFurnaceInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/BlastFurnaceInventoryTranslator.java
@@ -28,10 +28,11 @@ package org.geysermc.geyser.translator.inventory.furnace;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.geysermc.geyser.inventory.BedrockContainerSlot;
+import org.geysermc.geyser.level.block.Blocks;
public class BlastFurnaceInventoryTranslator extends AbstractFurnaceInventoryTranslator {
public BlastFurnaceInventoryTranslator() {
- super("minecraft:blast_furnace[facing=north,lit=false]", ContainerType.BLAST_FURNACE);
+ super(Blocks.BLAST_FURNACE, ContainerType.BLAST_FURNACE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/FurnaceInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/FurnaceInventoryTranslator.java
index 95a79a93e..bc96f7105 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/FurnaceInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/FurnaceInventoryTranslator.java
@@ -28,10 +28,11 @@ package org.geysermc.geyser.translator.inventory.furnace;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.geysermc.geyser.inventory.BedrockContainerSlot;
+import org.geysermc.geyser.level.block.Blocks;
public class FurnaceInventoryTranslator extends AbstractFurnaceInventoryTranslator {
public FurnaceInventoryTranslator() {
- super("minecraft:furnace[facing=north,lit=false]", ContainerType.FURNACE);
+ super(Blocks.FURNACE, ContainerType.FURNACE);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/SmokerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/SmokerInventoryTranslator.java
index 2f87f3b13..380446f09 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/SmokerInventoryTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/SmokerInventoryTranslator.java
@@ -28,10 +28,11 @@ package org.geysermc.geyser.translator.inventory.furnace;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.geysermc.geyser.inventory.BedrockContainerSlot;
+import org.geysermc.geyser.level.block.Blocks;
public class SmokerInventoryTranslator extends AbstractFurnaceInventoryTranslator {
public SmokerInventoryTranslator() {
- super("minecraft:smoker[facing=north,lit=false]", ContainerType.SMOKER);
+ super(Blocks.SMOKER, ContainerType.SMOKER);
}
@Override
diff --git a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java
index 768c94791..251aacba8 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/item/ItemTranslator.java
@@ -42,6 +42,7 @@ import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
+import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.CustomSkull;
@@ -52,20 +53,12 @@ import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.InventoryUtils;
-import org.geysermc.mcprotocollib.protocol.data.game.Identifier;
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.AdventureModePredicate;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
-import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemAttributeModifiers;
+import org.geysermc.mcprotocollib.protocol.data.game.item.component.*;
import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
public final class ItemTranslator {
@@ -185,11 +178,11 @@ public final class ItemTranslator {
translateCustomItem(components, builder, bedrockItem);
if (components != null) {
- // Translate the canDestroy and canPlaceOn Java NBT
+ // Translate the canDestroy and canPlaceOn Java components
AdventureModePredicate canDestroy = components.get(DataComponentType.CAN_BREAK);
AdventureModePredicate canPlaceOn = components.get(DataComponentType.CAN_PLACE_ON);
- String[] canBreak = getCanModify(canDestroy);
- String[] canPlace = getCanModify(canPlaceOn);
+ String[] canBreak = getCanModify(session, canDestroy);
+ String[] canPlace = getCanModify(session, canPlaceOn);
if (canBreak != null) {
builder.canBreak(canBreak);
}
@@ -325,27 +318,42 @@ public final class ItemTranslator {
* @param canModifyJava the list of items in Java
* @return the new list of items in Bedrock
*/
- // TODO this is now more complicated in 1.20.5. Yippee!
- private static String @Nullable [] getCanModify(@Nullable AdventureModePredicate canModifyJava) {
+ // TODO blocks by tag, maybe NBT, maybe properties
+ // Blocks by tag will be easy enough, most likely, we just need to... save all block tags.
+ // Probably do that with Guava interning around sessions
+ private static String @Nullable [] getCanModify(GeyserSession session, @Nullable AdventureModePredicate canModifyJava) {
if (canModifyJava == null) {
return null;
}
List predicates = canModifyJava.getPredicates();
- if (predicates.size() > 0) {
- String[] canModifyBedrock = new String[predicates.size()];
- for (int i = 0; i < canModifyBedrock.length; i++) {
- // Get the Java identifier of the block that can be placed
- String location = predicates.get(i).getLocation();
- if (location == null) {
- canModifyBedrock[i] = ""; // So it'll serialize
- continue; // ???
+ if (!predicates.isEmpty()) {
+ List canModifyBedrock = new ArrayList<>(); // This used to be an array, but we need to be flexible with what blocks can be supported
+ for (int i = 0; i < predicates.size(); i++) {
+ HolderSet holderSet = predicates.get(i).getBlocks();
+ if (holderSet == null) {
+ continue;
+ }
+ int[] holders = holderSet.getHolders();
+ if (holders == null) {
+ continue;
+ }
+ // Holders is an int state of Java block IDs (not block states)
+ for (int blockId : holders) {
+ // Get the Bedrock identifier of the item
+ // This will unfortunately be limited - for example, beds and banners will be translated weirdly
+ Block block = BlockRegistries.JAVA_BLOCKS.get(blockId);
+ if (block == null) {
+ continue;
+ }
+ String identifier = session.getBlockMappings().getJavaToBedrockIdentifiers().get(block.javaId());
+ if (identifier == null) {
+ canModifyBedrock.add(block.javaIdentifier().value());
+ } else {
+ canModifyBedrock.add(identifier);
+ }
}
- String block = Identifier.formalize(location);
- // Get the Bedrock identifier of the item and replace it.
- // This will unfortunately be limited - for example, beds and banners will be translated weirdly
- canModifyBedrock[i] = BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.getOrDefault(block, block).replace("minecraft:", "");
}
- return canModifyBedrock;
+ return canModifyBedrock.toArray(new String[0]);
}
return null;
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java
index 81f58214c..8b6f627e1 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BannerBlockEntityTranslator.java
@@ -30,7 +30,8 @@ import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.item.type.BannerItem;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.BannerBlock;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@@ -39,10 +40,9 @@ import java.util.List;
@BlockEntity(type = BlockEntityType.BANNER)
public class BannerBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) {
- int bannerColor = BlockStateValues.getBannerColor(blockState);
- if (bannerColor != -1) {
- bedrockNbt.putInt("Base", 15 - bannerColor);
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) {
+ if (blockState.block() instanceof BannerBlock banner) {
+ bedrockNbt.putInt("Base", 15 - banner.dyeColor());
}
if (javaNbt == null) {
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java
index f7dee2864..9b5248785 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BeaconBlockEntityTranslator.java
@@ -27,13 +27,14 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@BlockEntity(type = BlockEntityType.BEACON)
public class BeaconBlockEntityTranslator extends BlockEntityTranslator {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
int primary = javaNbt.getInt("primary");
// The effects here generally map one-to-one Java <-> Bedrock. Only the newer ones get more complicated
bedrockNbt.putInt("primary", primary == -1 ? 0 : primary);
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java
index 720ffea3c..7622e6d28 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedBlockEntityTranslator.java
@@ -27,19 +27,15 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.BedBlock;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@BlockEntity(type = BlockEntityType.BED)
public class BedBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
- byte bedcolor = BlockStateValues.getBedColor(blockState);
- // Just in case...
- if (bedcolor == -1) {
- bedcolor = 0;
- }
- bedrockNbt.putByte("color", bedcolor);
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
+ bedrockNbt.putByte("color", (byte) (blockState.block() instanceof BedBlock bed ? bed.dyeColor() : 0));
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockChunkWantsBlockEntityTag.java
similarity index 59%
rename from core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntityTranslator.java
rename to core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockChunkWantsBlockEntityTag.java
index a55fa8a62..189fb2c65 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockChunkWantsBlockEntityTag.java
@@ -27,32 +27,18 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.session.GeyserSession;
/**
- * Pistons are a special case where they are only a block entity on Bedrock.
+ * Implemented only if a block is a block entity in Bedrock and not Java Edition.
*/
-public class PistonBlockEntityTranslator {
+public interface BedrockChunkWantsBlockEntityTag extends RequiresBlockState {
/**
- * Used in ChunkUtils to determine if the block is a piston.
- *
+ * Get the tag of the Bedrock-only block entity. Used during chunk loading.
+ * @param position Bedrock position of block.
* @param blockState Java BlockState of block.
- * @return if block is a piston or not.
+ * @return Bedrock tag
*/
- public static boolean isBlock(int blockState) {
- return BlockStateValues.getPistonValues().containsKey(blockState);
- }
-
- /**
- * Calculates the Nukkit CompoundTag to send to the client on chunk
- *
- * @param blockState Java block state of block.
- * @param position Bedrock position of piston.
- * @return Bedrock tag of piston.
- */
- public static NbtMap getTag(int blockState, Vector3i position) {
- boolean extended = BlockStateValues.getPistonValues().get(blockState);
- boolean sticky = BlockStateValues.isStickyPiston(blockState);
- return PistonBlockEntity.buildStaticPistonTag(position, extended, sticky);
- }
+ NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState);
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java
deleted file mode 100644
index 051986473..000000000
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * @author GeyserMC
- * @link https://github.com/GeyserMC/Geyser
- */
-
-package org.geysermc.geyser.translator.level.block.entity;
-
-import org.checkerframework.checker.nullness.qual.Nullable;
-import org.cloudburstmc.math.vector.Vector3i;
-import org.cloudburstmc.nbt.NbtList;
-import org.cloudburstmc.nbt.NbtMap;
-import org.cloudburstmc.nbt.NbtType;
-import org.geysermc.geyser.level.block.BlockStateValues;
-import org.geysermc.geyser.session.GeyserSession;
-
-/**
- * Implemented only if a block is a block entity in Bedrock and not Java Edition.
- */
-public interface BedrockOnlyBlockEntity extends RequiresBlockState {
- /**
- * Determines if block is part of class
- * @param blockState BlockState to be compared
- * @return true if part of the class
- */
- boolean isBlock(int blockState);
-
- /**
- * Update the block on Bedrock Edition.
- * @param session GeyserConnection.
- * @param blockState The Java block state.
- * @param position The Bedrock block position.
- */
- void updateBlock(GeyserSession session, int blockState, Vector3i position);
-
- /**
- * Get the tag of the Bedrock-only block entity
- * @param position Bedrock position of block.
- * @param blockState Java BlockState of block.
- * @return Bedrock tag, or null if not a Bedrock-only Block Entity
- */
- static @Nullable NbtMap getTag(GeyserSession session, Vector3i position, int blockState) {
- if (FlowerPotBlockEntityTranslator.isFlowerBlock(blockState)) {
- return FlowerPotBlockEntityTranslator.getTag(session, blockState, position);
- } else if (PistonBlockEntityTranslator.isBlock(blockState)) {
- return PistonBlockEntityTranslator.getTag(blockState, position);
- } else if (BlockStateValues.isCauldron(blockState)) {
- // As of 1.18.30: this is required to make rendering not look weird on chunk load (lava and snow cauldrons look dim)
- return NbtMap.builder()
- .putString("id", "Cauldron")
- .putByte("isMovable", (byte) 0)
- .putShort("PotionId", (short) -1)
- .putShort("PotionType", (short) -1)
- .putList("Items", NbtType.END, NbtList.EMPTY)
- .putInt("x", position.getX())
- .putInt("y", position.getY())
- .putInt("z", position.getZ())
- .build();
- }
- return null;
- }
-}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java
index 6df7781be..ae44dd134 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BlockEntityTranslator.java
@@ -26,8 +26,10 @@
package org.geysermc.geyser.translator.level.block.entity;
import org.checkerframework.checker.nullness.qual.Nullable;
+import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.BlockEntityUtils;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@@ -39,9 +41,9 @@ public abstract class BlockEntityTranslator {
protected BlockEntityTranslator() {
}
- public abstract void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState);
+ public abstract void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState);
- public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, int blockState) {
+ public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, BlockState blockState) {
NbtMapBuilder tagBuilder = getConstantBedrockTag(type, x, y, z);
if (javaNbt != null || this instanceof RequiresBlockState) {
// Always process tags if the block state is part of the tag.
@@ -55,6 +57,10 @@ public abstract class BlockEntityTranslator {
return getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(type), x, y, z);
}
+ public static NbtMapBuilder getConstantBedrockTag(String bedrockId, Vector3i position) {
+ return getConstantBedrockTag(bedrockId, position.getX(), position.getY(), position.getZ());
+ }
+
public static NbtMapBuilder getConstantBedrockTag(String bedrockId, int x, int y, int z) {
return NbtMap.builder()
.putInt("x", x)
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java
index b4012236b..f0d632041 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BrushableBlockEntityTranslator.java
@@ -29,7 +29,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.item.Items;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@@ -38,7 +39,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
public class BrushableBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) {
if (javaNbt == null) {
return;
}
@@ -70,6 +71,6 @@ public class BrushableBlockEntityTranslator extends BlockEntityTranslator implem
// controls which side the item protrudes from
bedrockNbt.putByte("brush_direction", hitDirection);
// controls how much the item protrudes
- bedrockNbt.putInt("brush_count", BlockStateValues.getBrushProgress(blockState));
+ bedrockNbt.putInt("brush_count", blockState.getValue(Properties.DUSTED));
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java
index 699319bb6..fb71a84cc 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CampfireBlockEntityTranslator.java
@@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
@@ -38,7 +39,7 @@ import java.util.List;
@BlockEntity(type = BlockEntityType.CAMPFIRE)
public class CampfireBlockEntityTranslator extends BlockEntityTranslator {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
List items = javaNbt.getList("Items", NbtType.COMPOUND);
if (items != null) {
int i = 1;
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java
index 0e00a19a8..b363de530 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/CommandBlockBlockEntityTranslator.java
@@ -27,7 +27,8 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@@ -35,12 +36,12 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
@BlockEntity(type = BlockEntityType.COMMAND_BLOCK)
public class CommandBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
if (javaNbt == null || javaNbt.size() < 5) {
return; // These values aren't here
}
// Java infers from the block state, but Bedrock needs it in the tag
- bedrockNbt.putByte("conditionalMode", BlockStateValues.getCommandBlockValues().getOrDefault(blockState, (byte) 0));
+ bedrockNbt.putBoolean("conditionalMode", blockState.getValue(Properties.CONDITIONAL));
// Java and Bedrock values
bedrockNbt.putByte("conditionMet", javaNbt.getByte("conditionMet"));
bedrockNbt.putByte("auto", javaNbt.getByte("auto"));
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java
index b24558b45..33c884c55 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DecoratedPotBlockEntityTranslator.java
@@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@@ -35,7 +36,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
public class DecoratedPotBlockEntityTranslator extends BlockEntityTranslator {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
if (javaNbt == null) {
return;
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java
index dcb39d22c..6fea10e2e 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java
@@ -25,39 +25,31 @@
package org.geysermc.geyser.translator.level.block.entity;
-import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.geyser.level.block.BlockStateValues;
-import org.geysermc.geyser.level.block.DoubleChestValue;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.ChestType;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.session.GeyserSession;
-import org.geysermc.geyser.util.BlockEntityUtils;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
/**
- * Chests have more block entity properties in Bedrock, which is solved by implementing the BedrockOnlyBlockEntity
+ * Chests have more block entity properties in Bedrock, which is solved by implementing the BedrockChunkWantsBlockEntityTag
*/
@BlockEntity(type = { BlockEntityType.CHEST, BlockEntityType.TRAPPED_CHEST })
-public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator implements BedrockOnlyBlockEntity {
- @Override
- public boolean isBlock(int blockState) {
- return BlockStateValues.getDoubleChestValues().containsKey(blockState);
- }
+public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
@Override
- public void updateBlock(GeyserSession session, int blockState, Vector3i position) {
- NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(BlockEntityType.CHEST), position.getX(), position.getY(), position.getZ());
- translateTag(session, tagBuilder, null, blockState);
- BlockEntityUtils.updateBlockEntity(session, tagBuilder.build(), position);
- }
-
- @Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
- DoubleChestValue chestValues = BlockStateValues.getDoubleChestValues().get(blockState);
- if (chestValues != null) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
+ if (!(blockState.is(Blocks.CHEST) || blockState.is(Blocks.TRAPPED_CHEST))) {
+ return;
+ }
+ if (blockState.getValue(Properties.CHEST_TYPE) != ChestType.SINGLE) {
int x = (int) bedrockNbt.get("x");
int z = (int) bedrockNbt.get("z");
- translateChestValue(bedrockNbt, chestValues, x, z);
+ translateChestValue(bedrockNbt, blockState, x, z);
}
}
@@ -65,32 +57,23 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl
* Add Bedrock block entity tags to a NbtMap based on Java properties
*
* @param builder the NbtMapBuilder to apply properties to
- * @param chestValues the position properties of this double chest
+ * @param state the BlockState of this double chest
* @param x the x position of this chest pair
* @param z the z position of this chest pair
*/
- public static void translateChestValue(NbtMapBuilder builder, DoubleChestValue chestValues, int x, int z) {
+ public static void translateChestValue(NbtMapBuilder builder, BlockState state, int x, int z) {
// Calculate the position of the other chest based on the Java block state
- if (chestValues.isFacingEast()) {
- if (chestValues.isDirectionPositive()) {
- // East
- z = z + (chestValues.isLeft() ? 1 : -1);
- } else {
- // West
- z = z + (chestValues.isLeft() ? -1 : 1);
- }
- } else {
- if (chestValues.isDirectionPositive()) {
- // South
- x = x + (chestValues.isLeft() ? -1 : 1);
- } else {
- // North
- x = x + (chestValues.isLeft() ? 1 : -1);
- }
+ Direction facing = state.getValue(Properties.HORIZONTAL_FACING);
+ boolean isLeft = state.getValue(Properties.CHEST_TYPE) == ChestType.LEFT;
+ switch (facing) {
+ case EAST -> z = z + (isLeft ? 1 : -1);
+ case WEST -> z = z + (isLeft ? -1 : 1);
+ case SOUTH -> x = x + (isLeft ? -1 : 1);
+ case NORTH -> x = x + (isLeft ? 1 : -1);
}
builder.putInt("pairx", x);
builder.putInt("pairz", z);
- if (!chestValues.isLeft()) {
+ if (!isLeft) {
builder.putInt("pairlead", (byte) 1);
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EmptyBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EmptyBlockEntityTranslator.java
index 9ce0aff0a..88029dc2d 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EmptyBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EmptyBlockEntityTranslator.java
@@ -27,10 +27,11 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
public class EmptyBlockEntityTranslator extends BlockEntityTranslator {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java
index 97428eec1..36731bdff 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/EndGatewayBlockEntityTranslator.java
@@ -31,13 +31,14 @@ import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@BlockEntity(type = BlockEntityType.END_GATEWAY)
public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
bedrockNbt.putInt("Age", (int) javaNbt.getLong("Age"));
// Java sometimes does not provide this tag, but Bedrock crashes if it doesn't exist
// Linked coordinates
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java
index 53f32682c..45eee156b 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java
@@ -28,14 +28,15 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@BlockEntity(type = BlockEntityType.JIGSAW)
public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) {
if (javaNbt == null) {
return;
}
@@ -46,7 +47,7 @@ public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator impl
} else {
// Tag is not present in at least 1.14.4 Paper
// Minecraft 1.18.1 deliberately has a fallback here, but not for any other value
- bedrockNbt.putString("joint", BlockStateValues.getHorizontalFacingJigsaws().contains(blockState) ? "aligned" : "rollable");
+ bedrockNbt.putString("joint", blockState.getValue(Properties.ORIENTATION).isHorizontal() ? "aligned" : "rollable");
}
bedrockNbt.putString("name", javaNbt.getString("name"));
bedrockNbt.putString("target_pool", javaNbt.getString("target_pool"));
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java
index 78e71000a..350ce8c3e 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java
@@ -25,19 +25,25 @@
package org.geysermc.geyser.translator.level.block.entity;
-import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
+import it.unimi.dsi.fastutil.ints.IntArrays;
+import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
+import lombok.Getter;
import org.cloudburstmc.math.vector.Vector3d;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
-import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
-import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
-import lombok.Getter;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.block.type.PistonBlock;
import org.geysermc.geyser.level.physics.Axis;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.level.physics.CollisionManager;
@@ -49,6 +55,7 @@ import org.geysermc.geyser.translator.collision.BlockCollision;
import org.geysermc.geyser.util.BlockEntityUtils;
import org.geysermc.geyser.util.BlockUtils;
import org.geysermc.geyser.util.ChunkUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
import java.util.LinkedList;
import java.util.Map;
@@ -68,11 +75,11 @@ public class PistonBlockEntity {
/**
* A map of attached block positions to Java ids.
*/
- private final Object2IntMap attachedBlocks = new Object2IntOpenHashMap<>();
+ private final Object2ObjectMap attachedBlocks = new Object2ObjectOpenHashMap<>();
/**
* A flattened array of the positions of attached blocks, stored in XYZ order.
*/
- private int[] flattenedAttachedBlocks = new int[0];
+ private int[] flattenedAttachedBlocks = IntArrays.EMPTY_ARRAY;
private boolean placedFinalBlocks = true;
@@ -95,7 +102,7 @@ public class PistonBlockEntity {
static {
// Create a ~1 x ~0.5 x ~1 bounding box above the honey block
- BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(BlockStateValues.JAVA_HONEY_BLOCK_ID);
+ BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(Blocks.HONEY_BLOCK.defaultBlockState().javaId());
if (blockCollision == null) {
throw new RuntimeException("Failed to find honey block collision");
}
@@ -157,7 +164,7 @@ public class PistonBlockEntity {
BlockEntityUtils.updateBlockEntity(session, buildPistonTag(), position);
}
- public void setAction(PistonValueType action, Object2IntMap attachedBlocks) {
+ public void setAction(PistonValueType action, Map attachedBlocks) {
// Don't check if this.action == action, since on some Paper versions BlockPistonRetractEvent is called multiple times
// with the first 1-2 events being empty.
placeFinalBlocks();
@@ -220,12 +227,12 @@ public class PistonBlockEntity {
private void removePistonHead() {
Vector3i blockInFront = position.add(orientation.getUnitVector());
- int blockId = session.getGeyser().getWorldManager().getBlockAt(session, blockInFront);
- if (BlockStateValues.isPistonHead(blockId)) {
- ChunkUtils.updateBlock(session, BlockStateValues.JAVA_AIR_ID, blockInFront);
- } else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && blockId == BlockStateValues.JAVA_AIR_ID) {
+ BlockState state = session.getGeyser().getWorldManager().blockAt(session, blockInFront);
+ if (state.is(Blocks.PISTON_HEAD)) {
+ ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront);
+ } else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && state.is(Blocks.AIR)) {
// Spigot removes the piston head from the cache, but we need to send the block update ourselves
- ChunkUtils.updateBlock(session, BlockStateValues.JAVA_AIR_ID, blockInFront);
+ ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront);
}
}
@@ -254,13 +261,13 @@ public class PistonBlockEntity {
if (!blocksChecked.add(blockPos)) {
continue;
}
- int blockId = session.getGeyser().getWorldManager().getBlockAt(session, blockPos);
- if (blockId == BlockStateValues.JAVA_AIR_ID) {
+ BlockState state = session.getGeyser().getWorldManager().blockAt(session, blockPos);
+ if (state.block() == Blocks.AIR) {
continue;
}
- if (BlockStateValues.canPistonMoveBlock(blockId, action == PistonValueType.PUSHING)) {
- attachedBlocks.put(blockPos, blockId);
- if (BlockStateValues.isBlockSticky(blockId)) {
+ if (BlockStateValues.canPistonMoveBlock(state, action == PistonValueType.PUSHING)) {
+ attachedBlocks.put(blockPos, state);
+ if (BlockStateValues.isBlockSticky(state)) {
// For honey blocks and slime blocks check the blocks adjacent to it
for (Direction direction : Direction.VALUES) {
Vector3i offset = direction.getUnitVector();
@@ -277,13 +284,13 @@ public class PistonBlockEntity {
if (action == PistonValueType.PULLING && position.add(directionOffset).equals(adjacentPos)) {
continue;
}
- int adjacentBlockId = session.getGeyser().getWorldManager().getBlockAt(session, adjacentPos);
- if (adjacentBlockId != BlockStateValues.JAVA_AIR_ID && BlockStateValues.isBlockAttached(blockId, adjacentBlockId) && BlockStateValues.canPistonMoveBlock(adjacentBlockId, false)) {
+ BlockState adjacentBlockState = session.getGeyser().getWorldManager().blockAt(session, adjacentPos);
+ if (adjacentBlockState.block() != Blocks.AIR && BlockStateValues.isBlockAttached(state, adjacentBlockState) && BlockStateValues.canPistonMoveBlock(adjacentBlockState, false)) {
// If it is another slime/honey block we need to check its adjacent blocks
- if (BlockStateValues.isBlockSticky(adjacentBlockId)) {
+ if (BlockStateValues.isBlockSticky(adjacentBlockState)) {
blocksToCheck.add(adjacentPos);
} else {
- attachedBlocks.put(adjacentPos, adjacentBlockId);
+ attachedBlocks.put(adjacentPos, adjacentBlockState);
blocksChecked.add(adjacentPos);
blocksToCheck.add(adjacentPos.add(movement));
}
@@ -292,7 +299,7 @@ public class PistonBlockEntity {
}
// Check next block in line
blocksToCheck.add(blockPos.add(movement));
- } else if (!BlockStateValues.canPistonDestroyBlock(blockId)) {
+ } else if (!BlockStateValues.canPistonDestroyBlock(state)) {
// Block can't be moved or destroyed, so it blocks all block movement
moveBlocks = false;
break;
@@ -322,7 +329,7 @@ public class PistonBlockEntity {
*/
private void removeBlocks() {
for (Vector3i blockPos : attachedBlocks.keySet()) {
- ChunkUtils.updateBlock(session, BlockStateValues.JAVA_AIR_ID, blockPos);
+ ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockPos);
}
if (action != PistonValueType.PUSHING) {
removePistonHead();
@@ -349,24 +356,26 @@ public class PistonBlockEntity {
playerBoundingBox.setSizeZ(playerBoundingBox.getSizeZ() - shrink.getZ());
// Resolve collision with the piston head
- int pistonHeadId = BlockStateValues.getPistonHead(orientation);
+ BlockState pistonHeadId = Blocks.PISTON_HEAD.defaultBlockState()
+ .withValue(Properties.SHORT, false)
+ .withValue(Properties.FACING, orientation);
pushPlayerBlock(pistonHeadId, getPistonHeadPos().toDouble(), blockMovement, playerBoundingBox);
// Resolve collision with any attached moving blocks, but skip slime blocks
// This prevents players from being launched by slime blocks covered by other blocks
- for (Object2IntMap.Entry entry : attachedBlocks.object2IntEntrySet()) {
- int blockId = entry.getIntValue();
- if (blockId != BlockStateValues.JAVA_SLIME_BLOCK_ID) {
+ for (Map.Entry entry : Object2ObjectMaps.fastIterable(attachedBlocks)) {
+ BlockState state = entry.getValue();
+ if (!state.is(Blocks.SLIME_BLOCK)) {
Vector3d blockPos = entry.getKey().toDouble();
- pushPlayerBlock(blockId, blockPos, blockMovement, playerBoundingBox);
+ pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox);
}
}
// Resolve collision with slime blocks
- for (Object2IntMap.Entry entry : attachedBlocks.object2IntEntrySet()) {
- int blockId = entry.getIntValue();
- if (blockId == BlockStateValues.JAVA_SLIME_BLOCK_ID) {
+ for (Map.Entry entry : Object2ObjectMaps.fastIterable(attachedBlocks)) {
+ BlockState state = entry.getValue();
+ if (state.is(Blocks.SLIME_BLOCK)) {
Vector3d blockPos = entry.getKey().toDouble();
- pushPlayerBlock(blockId, blockPos, blockMovement, playerBoundingBox);
+ pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox);
}
}
@@ -462,7 +471,7 @@ public class PistonBlockEntity {
return maxIntersection;
}
- private void pushPlayerBlock(int javaId, Vector3d startingPos, double blockMovement, BoundingBox playerBoundingBox) {
+ private void pushPlayerBlock(BlockState state, Vector3d startingPos, double blockMovement, BoundingBox playerBoundingBox) {
PistonCache pistonCache = session.getPistonCache();
Vector3d movement = getMovement().toDouble();
// Check if the player collides with the movingBlock block entity
@@ -470,14 +479,14 @@ public class PistonBlockEntity {
if (SOLID_BOUNDING_BOX.checkIntersection(finalBlockPos, playerBoundingBox)) {
pistonCache.setPlayerCollided(true);
- if (javaId == BlockStateValues.JAVA_SLIME_BLOCK_ID) {
+ if (state.is(Blocks.SLIME_BLOCK)) {
pistonCache.setPlayerSlimeCollision(true);
applySlimeBlockMotion(finalBlockPos, Vector3d.from(playerBoundingBox.getMiddleX(), playerBoundingBox.getMiddleY(), playerBoundingBox.getMiddleZ()));
}
}
Vector3d blockPos = startingPos.add(movement.mul(blockMovement));
- if (javaId == BlockStateValues.JAVA_HONEY_BLOCK_ID && isPlayerAttached(blockPos, playerBoundingBox)) {
+ if (state.is(Blocks.HONEY_BLOCK) && isPlayerAttached(blockPos, playerBoundingBox)) {
pistonCache.setPlayerCollided(true);
pistonCache.setPlayerAttachedToHoney(true);
@@ -485,7 +494,7 @@ public class PistonBlockEntity {
pistonCache.displacePlayer(movement.mul(delta));
} else {
// Move the player out of collision
- BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(javaId);
+ BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(state.javaId());
if (blockCollision != null) {
Vector3d extend = movement.mul(Math.min(1 - blockMovement, 0.5));
Direction movementDirection = orientation;
@@ -498,7 +507,7 @@ public class PistonBlockEntity {
pistonCache.setPlayerCollided(true);
pistonCache.displacePlayer(movement.mul(intersection + 0.01d));
- if (javaId == BlockStateValues.JAVA_SLIME_BLOCK_ID) {
+ if (state.is(Blocks.SLIME_BLOCK)) {
pistonCache.setPlayerSlimeCollision(true);
applySlimeBlockMotion(blockPos, Vector3d.from(playerBoundingBox.getMiddleX(), playerBoundingBox.getMiddleY(), playerBoundingBox.getMiddleZ()));
}
@@ -508,7 +517,7 @@ public class PistonBlockEntity {
}
private BlockCollision getCollision(Vector3i blockPos) {
- return BlockUtils.getCollision(getAttachedBlockId(blockPos));
+ return BlockUtils.getCollision(getAttachedBlockId(blockPos).javaId());
}
/**
@@ -532,7 +541,7 @@ public class PistonBlockEntity {
double y = blockPos.getY() + movementVec.getY() * movementProgress;
double z = blockPos.getZ() + movementVec.getZ() * movementProgress;
double adjustedMovement = blockCollision.computeCollisionOffset(x, y, z, boundingBox, axis, movement);
- if (getAttachedBlockId(blockPos) == BlockStateValues.JAVA_SLIME_BLOCK_ID && adjustedMovement != movement) {
+ if (getAttachedBlockId(blockPos).is(Blocks.SLIME_BLOCK) && adjustedMovement != movement) {
session.getPistonCache().setPlayerSlimeCollision(true);
}
return adjustedMovement;
@@ -556,11 +565,13 @@ public class PistonBlockEntity {
return false;
}
- private int getAttachedBlockId(Vector3i blockPos) {
+ private BlockState getAttachedBlockId(Vector3i blockPos) {
if (blockPos.equals(getPistonHeadPos())) {
- return BlockStateValues.getPistonHead(orientation);
+ return Blocks.PISTON_HEAD.defaultBlockState()
+ .withValue(Properties.SHORT, false)
+ .withValue(Properties.FACING, orientation);
} else {
- return attachedBlocks.getOrDefault(blockPos, BlockStateValues.JAVA_AIR_ID);
+ return attachedBlocks.getOrDefault(blockPos, Blocks.AIR.defaultBlockState());
}
}
@@ -581,12 +592,12 @@ public class PistonBlockEntity {
playerBoundingBox.setSizeX(playerBoundingBox.getSizeX() + 0.5);
playerBoundingBox.setSizeZ(playerBoundingBox.getSizeZ() + 0.5);
}
- attachedBlocks.forEach((blockPos, javaId) -> {
+ attachedBlocks.forEach((blockPos, state) -> {
Vector3i newPos = blockPos.add(movement);
if (SOLID_BOUNDING_BOX.checkIntersection(blockPos.toDouble(), playerBoundingBox) ||
SOLID_BOUNDING_BOX.checkIntersection(newPos.toDouble(), playerBoundingBox)) {
session.getPistonCache().setPlayerCollided(true);
- if (javaId == BlockStateValues.JAVA_SLIME_BLOCK_ID) {
+ if (state.is(Blocks.SLIME_BLOCK)) {
session.getPistonCache().setPlayerSlimeCollision(true);
}
// Don't place moving blocks that collide with the player
@@ -602,7 +613,7 @@ public class PistonBlockEntity {
updateBlockPacket.setDataLayer(0);
session.sendUpstreamPacket(updateBlockPacket);
// Update moving block with correct details
- BlockEntityUtils.updateBlockEntity(session, buildMovingBlockTag(newPos, javaId, position), newPos);
+ BlockEntityUtils.updateBlockEntity(session, buildMovingBlockTag(newPos, state, position), newPos);
});
}
@@ -619,17 +630,19 @@ public class PistonBlockEntity {
}
placedFinalBlocks = true;
Vector3i movement = getMovement();
- attachedBlocks.forEach((blockPos, javaId) -> {
+ attachedBlocks.forEach((blockPos, state) -> {
blockPos = blockPos.add(movement);
// Don't place blocks that collide with the player
if (!SOLID_BOUNDING_BOX.checkIntersection(blockPos.toDouble(), session.getCollisionManager().getPlayerBoundingBox())) {
- ChunkUtils.updateBlock(session, javaId, blockPos);
+ ChunkUtils.updateBlock(session, state, blockPos);
}
});
if (action == PistonValueType.PUSHING) {
Vector3i pistonHeadPos = getPistonHeadPos().add(movement);
if (!SOLID_BOUNDING_BOX.checkIntersection(pistonHeadPos.toDouble(), session.getCollisionManager().getPlayerBoundingBox())) {
- ChunkUtils.updateBlock(session, BlockStateValues.getPistonHead(orientation), pistonHeadPos);
+ ChunkUtils.updateBlock(session, Blocks.PISTON_HEAD.defaultBlockState()
+ .withValue(Properties.SHORT, false)
+ .withValue(Properties.FACING, orientation), pistonHeadPos);
}
}
}
@@ -730,18 +743,14 @@ public class PistonBlockEntity {
* @return A piston data tag
*/
private NbtMap buildPistonTag() {
- NbtMapBuilder builder = NbtMap.builder()
- .putString("id", "PistonArm")
+ NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("PistonArm", position)
.putIntArray("AttachedBlocks", flattenedAttachedBlocks)
.putFloat("Progress", progress)
.putFloat("LastProgress", lastProgress)
.putByte("NewState", getState())
.putByte("State", getState())
.putBoolean("Sticky", sticky)
- .putBoolean("isMovable", false)
- .putInt("x", position.getX())
- .putInt("y", position.getY())
- .putInt("z", position.getZ());
+ .putBoolean("isMovable", false);
return builder.build();
}
@@ -754,17 +763,13 @@ public class PistonBlockEntity {
* @return A piston data tag for a fully extended/retracted piston
*/
public static NbtMap buildStaticPistonTag(Vector3i position, boolean extended, boolean sticky) {
- NbtMapBuilder builder = NbtMap.builder()
- .putString("id", "PistonArm")
+ NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("PistonArm", position)
.putFloat("Progress", extended ? 1.0f : 0.0f)
.putFloat("LastProgress", extended ? 1.0f : 0.0f)
.putByte("NewState", (byte) (extended ? 2 : 0))
.putByte("State", (byte) (extended ? 2 : 0))
.putBoolean("Sticky", sticky)
- .putBoolean("isMovable", false)
- .putInt("x", position.getX())
- .putInt("y", position.getY())
- .putInt("z", position.getZ());
+ .putBoolean("isMovable", false);
return builder.build();
}
@@ -772,26 +777,22 @@ public class PistonBlockEntity {
* Create a moving block tag of a block that will be moved by a piston
*
* @param position The ending position of the block (The location of the movingBlock block entity)
- * @param javaId The Java Id of the block that is moving
+ * @param state The Java BlockState of the block that is moving
* @param pistonPosition The position for the base of the piston that's moving the block
* @return A moving block data tag
*/
- private NbtMap buildMovingBlockTag(Vector3i position, int javaId, Vector3i pistonPosition) {
+ private NbtMap buildMovingBlockTag(Vector3i position, BlockState state, Vector3i pistonPosition) {
// Get Bedrock block state data
- NbtMap movingBlock = session.getBlockMappings().getBedrockBlock(javaId).getState();
- NbtMapBuilder builder = NbtMap.builder()
- .putString("id", "MovingBlock")
+ NbtMap movingBlock = session.getBlockMappings().getBedrockBlock(state).getState();
+ NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("MovingBlock", position)
.putBoolean("expanding", action == PistonValueType.PUSHING)
.putCompound("movingBlock", movingBlock)
.putBoolean("isMovable", true)
.putInt("pistonPosX", pistonPosition.getX())
.putInt("pistonPosY", pistonPosition.getY())
- .putInt("pistonPosZ", pistonPosition.getZ())
- .putInt("x", position.getX())
- .putInt("y", position.getY())
- .putInt("z", position.getZ());
- if (PistonBlockEntityTranslator.isBlock(javaId)) {
- builder.putCompound("movingEntity", PistonBlockEntityTranslator.getTag(javaId, position));
+ .putInt("pistonPosZ", pistonPosition.getZ());
+ if (state.block() instanceof PistonBlock piston) {
+ builder.putCompound("movingEntity", piston.createTag(session, position, state));
}
return builder.build();
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java
index ba2ddd815..e6d19e492 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/ShulkerBoxBlockEntityTranslator.java
@@ -28,7 +28,8 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.ShulkerInventoryTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@@ -40,12 +41,7 @@ public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator imple
* where {@code tag} is passed as null.
*/
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) {
- byte direction = BlockStateValues.getShulkerBoxDirection(blockState);
- // Just in case...
- if (direction == -1) {
- direction = 1;
- }
- bedrockNbt.putByte("facing", direction);
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) {
+ bedrockNbt.putByte("facing", (byte) blockState.getValue(Properties.FACING).ordinal());
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java
index bbf0dbcb3..2a1ccb639 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SignBlockEntityTranslator.java
@@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.translator.text.MessageTranslator;
@@ -73,7 +74,7 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator {
}
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
bedrockNbt.putCompound("FrontText", translateSide(javaNbt.getCompound("front_text")));
bedrockNbt.putCompound("BackText", translateSide(javaNbt.getCompound("back_text")));
bedrockNbt.putBoolean("IsWaxed", javaNbt.getBoolean("is_waxed"));
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java
index b1ab017e8..cdbb20c44 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java
@@ -33,7 +33,9 @@ import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.geyser.GeyserImpl;
-import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.block.type.SkullBlock;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.SkullCache;
import org.geysermc.geyser.skin.SkinProvider;
@@ -50,16 +52,14 @@ import java.util.concurrent.ExecutionException;
public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
- byte skullVariant = BlockStateValues.getSkullVariant(blockState);
- float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f;
- // Just in case...
- if (skullVariant == -1) {
- skullVariant = 0;
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
+ Integer rotation = blockState.getValue(Properties.ROTATION_16);
+ if (rotation != null) {
+ // Could be a wall skull block otherwise, which has rotation in its Bedrock state
+ bedrockNbt.putFloat("Rotation", rotation * 22.5f);
}
- bedrockNbt.putFloat("Rotation", rotation);
- bedrockNbt.putByte("SkullType", skullVariant);
- if (BlockStateValues.isSkullPowered(blockState)) {
+ bedrockNbt.putByte("SkullType", (byte) (blockState.block() instanceof SkullBlock skull ? skull.skullType().bedrockId() : 0));
+ if (blockState.getValue(Properties.POWERED)) {
bedrockNbt.putBoolean("MouthMoving", true);
}
}
@@ -101,7 +101,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
return CompletableFuture.completedFuture(texture);
}
- public static @Nullable BlockDefinition translateSkull(GeyserSession session, NbtMap javaNbt, Vector3i blockPosition, int blockState) {
+ public static @Nullable BlockDefinition translateSkull(GeyserSession session, NbtMap javaNbt, Vector3i blockPosition, BlockState blockState) {
NbtMap profile = javaNbt.getCompound("profile");
if (profile.isEmpty()) {
session.getSkullCache().removeSkull(blockPosition);
@@ -145,7 +145,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
return null;
}
- private static void putSkull(GeyserSession session, Vector3i blockPosition, UUID uuid, String texturesProperty, int blockState) {
+ private static void putSkull(GeyserSession session, Vector3i blockPosition, UUID uuid, String texturesProperty, BlockState blockState) {
SkullCache.Skull skull = session.getSkullCache().putSkull(blockPosition, uuid, texturesProperty, blockState);
if (skull.getBlockDefinition() != null) {
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java
index edf71d384..4b6a630ba 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SpawnerBlockEntityTranslator.java
@@ -32,6 +32,7 @@ import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.geyser.entity.EntityDefinition;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@@ -40,7 +41,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
@Override
- public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, int blockState) {
+ public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, BlockState blockState) {
if (javaNbt == null) {
return super.getBlockEntityTag(session, type, x, y, z, javaNbt, blockState);
}
@@ -70,7 +71,7 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
}
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
Object current;
// TODO use primitive get and put methods
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java
index 4bb9c5676..79fb3da6b 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/StructureBlockBlockEntityTranslator.java
@@ -32,6 +32,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureMirror;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureRotation;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.StructureBlockUtils;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@@ -40,7 +41,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator {
@Override
- public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, int blockState) {
+ public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, BlockState blockState) {
if (javaNbt == null) {
return super.getBlockEntityTag(session, type, x, y, z, javaNbt, blockState);
}
@@ -73,7 +74,7 @@ public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator {
}
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
if (javaNbt.size() < 5) {
return; // These values aren't here
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java
index ff3f89f3f..a4c158a15 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/TrialSpawnerBlockEntityTranslator.java
@@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@@ -34,7 +35,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
public class TrialSpawnerBlockEntityTranslator extends BlockEntityTranslator {
@Override
- public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
+ public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
if (javaNbt == null) {
return;
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java
index 35c46ffd2..94368a6d4 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockBlockPickRequestTranslator.java
@@ -25,19 +25,20 @@
package org.geysermc.geyser.translator.protocol.bedrock;
-import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.packet.BlockPickRequestPacket;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.ItemFrameEntity;
-import org.geysermc.geyser.level.block.BlockStateValues;
-import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.BlockMapping;
-import org.geysermc.geyser.registry.type.ItemMapping;
+import org.geysermc.geyser.item.Items;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.type.BannerBlock;
+import org.geysermc.geyser.level.block.type.BlockState;
+import org.geysermc.geyser.level.block.type.SkullBlock;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.InventoryUtils;
+import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
@Translator(packet = BlockPickRequestPacket.class)
public class BedrockBlockPickRequestTranslator extends PacketTranslator {
@@ -45,10 +46,10 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator session.ensureInEventLoop(() -> {
if (components == null) {
- pickItem(session, blockMapping);
+ pickItem(session, blockToPick);
return;
}
- // I don't really like this... I'd rather get an ID from the block mapping I think
- ItemMapping mapping = session.getItemMappings().getMapping(blockMapping.getPickItem());
-
- ItemStack itemStack = new ItemStack(mapping.getJavaItem().javaId(), 1, components);
+ ItemStack itemStack = new ItemStack(blockToPick.block().asItem().javaId(), 1, components);
InventoryUtils.findOrCreateItem(session, itemStack);
}));
return;
}
- pickItem(session, blockMapping);
+ pickItem(session, blockToPick);
}
- private void pickItem(GeyserSession session, BlockMapping blockToPick) {
- InventoryUtils.findOrCreateItem(session, blockToPick.getPickItem());
+ private void pickItem(GeyserSession session, BlockState state) {
+ InventoryUtils.findOrCreateItem(session, state.block().pickItem(state));
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java
index 322d64cce..8d4df6f3f 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java
@@ -26,8 +26,8 @@
package org.geysermc.geyser.translator.protocol.bedrock;
import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket;
-import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.GeyserImpl;
+import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
@@ -39,15 +39,17 @@ public class BedrockCommandRequestTranslator extends PacketTranslator
- * 1.16.210: only used in creative.
- * 1.20.70: no longer used.
- */
-@Translator(packet = ItemFrameDropItemPacket.class)
-public class BedrockItemFrameDropItemTranslator extends PacketTranslator {
-
- // TODO: Remove when 1.20.60 is no longer supported
- @Override
- public void translate(GeyserSession session, ItemFrameDropItemPacket packet) {
- Entity entity = ItemFrameEntity.getItemFrameEntity(session, packet.getBlockPosition());
- if (entity != null) {
- ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(entity.getEntityId(),
- InteractAction.ATTACK, Hand.MAIN_HAND, session.isSneaking());
- session.sendDownstreamGamePacket(interactPacket);
- }
- }
-}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java
index e6d3d4dce..31a2d74cf 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockLecternUpdateTranslator.java
@@ -25,11 +25,6 @@
package org.geysermc.geyser.translator.protocol.bedrock;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
-import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
-import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
-import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket;
-import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket;
import org.cloudburstmc.protocol.bedrock.packet.LecternUpdatePacket;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.LecternContainer;
@@ -38,6 +33,8 @@ import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.InventoryUtils;
+import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
+import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket;
/**
* Used to translate moving pages, or closing the inventory
@@ -47,61 +44,44 @@ public class BedrockLecternUpdateTranslator extends PacketTranslator currentJavaPage) {
+ for (int i = currentJavaPage; i < newJavaPage; i++) {
+ ServerboundContainerButtonClickPacket clickButtonPacket = new ServerboundContainerButtonClickPacket(session.getOpenInventory().getJavaId(), 2);
+ session.sendDownstreamGamePacket(clickButtonPacket);
}
-
- // Send as many click button packets as we need to
- // Java has the option to specify exact page numbers by adding 100 to the number, but buttonId variable
- // is a byte when transmitted over the network and therefore this stops us at 128
- if (newJavaPage > currentJavaPage) {
- for (int i = currentJavaPage; i < newJavaPage; i++) {
- ServerboundContainerButtonClickPacket clickButtonPacket = new ServerboundContainerButtonClickPacket(session.getOpenInventory().getJavaId(), 2);
- session.sendDownstreamGamePacket(clickButtonPacket);
- }
- } else {
- for (int i = currentJavaPage; i > newJavaPage; i--) {
- ServerboundContainerButtonClickPacket clickButtonPacket = new ServerboundContainerButtonClickPacket(session.getOpenInventory().getJavaId(), 1);
- session.sendDownstreamGamePacket(clickButtonPacket);
- }
+ } else {
+ for (int i = currentJavaPage; i > newJavaPage; i--) {
+ ServerboundContainerButtonClickPacket clickButtonPacket = new ServerboundContainerButtonClickPacket(session.getOpenInventory().getJavaId(), 1);
+ session.sendDownstreamGamePacket(clickButtonPacket);
}
}
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockTextTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockTextTranslator.java
index f696396ad..bac9b9ecc 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockTextTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockTextTranslator.java
@@ -36,13 +36,22 @@ public class BedrockTextTranslator extends PacketTranslator {
@Override
public void translate(GeyserSession session, TextPacket packet) {
- String message = MessageTranslator.convertToPlainText(packet.getMessage());
+ // Java trims all messages, and then checks for the leading slash
+ String message = MessageTranslator.convertToPlainText(
+ MessageTranslator.normalizeSpace(packet.getMessage())
+ );
if (message.isBlank()) {
// Java Edition (as of 1.17.1) just doesn't pass on these messages, so... we won't either!
return;
}
+ if (message.startsWith("/")) {
+ // Yes, Java actually allows whitespaces before commands and will still see those as valid
+ BedrockCommandRequestTranslator.handleCommand(session, message.substring(1));
+ return;
+ }
+
if (MessageTranslator.isTooLong(message, session)) {
return;
}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
index 887ea3c09..959797d41 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockActionTranslator.java
@@ -38,10 +38,11 @@ import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.ItemFrameEntity;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
-import org.geysermc.geyser.level.block.BlockStateValues;
-import org.geysermc.geyser.network.GameProtocol;
+import org.geysermc.geyser.level.block.Blocks;
+import org.geysermc.geyser.level.block.property.Properties;
+import org.geysermc.geyser.level.block.type.Block;
+import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.registry.BlockRegistries;
-import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.SkullCache;
@@ -159,7 +160,7 @@ public class BedrockActionTranslator extends PacketTranslator {
@@ -77,9 +78,9 @@ public class BedrockLevelSoundEventTranslator extends PacketTranslator {
+ /**
+ * Wait until the registries load before getting all the block names.
+ */
+ private static final Supplier ALL_BLOCK_NAMES = Suppliers.memoize(() -> BlockRegistries.JAVA_BLOCKS.get().stream().map(block -> block.javaIdentifier().toString()).toArray(String[]::new));
private static final String[] ALL_EFFECT_IDENTIFIERS = EntityUtils.getAllEffectIdentifiers();
private static final String[] ATTRIBUTES = AttributeType.Builtin.BUILTIN.values().stream().map(AttributeType::getIdentifier).toList().toArray(new String[0]);
private static final String[] ENUM_BOOLEAN = {"true", "false"};
@@ -246,7 +252,7 @@ public class JavaCommandsTranslator extends PacketTranslator CommandParam.FILE_PATH;
case BOOL -> ENUM_BOOLEAN;
case OPERATION -> CommandParam.OPERATOR; // ">=", "==", etc
- case BLOCK_STATE -> context.getBlockStates();
+ case BLOCK_STATE -> ALL_BLOCK_NAMES.get();
case ITEM_STACK -> context.getItemNames();
case COLOR -> VALID_COLORS;
case SCOREBOARD_SLOT -> VALID_SCOREBOARD_SLOTS;
@@ -286,7 +292,6 @@ public class JavaCommandsTranslator extends PacketTranslator {
@@ -134,6 +137,7 @@ public class JavaLoginTranslator extends PacketTranslator {
+ // todo: dump from client?
+ private static final Set KNOWN_PACK_IDS = Set.of("core", "update_1_21", "bundle", "trade_rebalance");
+
+ @Override
+ public void translate(GeyserSession session, ClientboundSelectKnownPacks packet) {
+ List knownPacks = new ArrayList<>(1);
+ for (KnownPack pack : packet.getKnownPacks()) {
+ if ("minecraft".equals(pack.getNamespace()) && GameProtocol.getJavaMinecraftVersion().equals(pack.getVersion())) {
+ // Implementation note: these won't always necessarily be equal.
+ // 1.20.5 versus 1.20.6 for example - same protocol version. A vanilla server for either version will gracefully accept either.
+ // If the versions mismatch, the registry will be sent over the network, though.
+ // For vanilla compliancy, to minimize network traffic, and for potential future behavior,
+ // We'll implement how the Java client does it.
+ if (KNOWN_PACK_IDS.contains(pack.getId())) {
+ knownPacks.add(pack);
+ }
+ }
+ }
+ session.sendDownstreamPacket(new ServerboundSelectKnownPacks(knownPacks));
+ }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java
index 0db62f21d..2a0c38221 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaUpdateRecipesTranslator.java
@@ -30,6 +30,7 @@ import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
+import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.RecipeUnlockingRequirement;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.MultiRecipeData;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.SmithingTrimRecipeData;
@@ -133,7 +134,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator= inventory.getSize()) {
GeyserLogger logger = session.getGeyser().getLogger();
@@ -111,14 +108,22 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator {
@@ -42,7 +43,7 @@ public class JavaBlockDestructionTranslator extends PacketTranslator {
@@ -62,7 +65,7 @@ public class JavaBlockEventTranslator extends PacketTranslator {
- blockEventPacket.setEventData(BlockStateValues.getNoteblockPitch(blockState));
+ blockEventPacket.setEventData(BlockState.of(blockState).getValue(Properties.NOTE));
session.sendUpstreamPacket(blockEventPacket);
});
} else if (value instanceof PistonValue pistonValue) {
@@ -75,27 +78,27 @@ public class JavaBlockEventTranslator extends PacketTranslator new PistonBlockEntity(session, pos, direction, true, true));
if (blockEntity.getAction() != action) {
- blockEntity.setAction(action, Object2IntMaps.emptyMap());
+ blockEntity.setAction(action, Object2ObjectMaps.emptyMap());
}
}
} else {
PistonBlockEntity blockEntity = pistonCache.getPistons().computeIfAbsent(position, pos -> {
- int blockId = session.getGeyser().getWorldManager().getBlockAt(session, position);
- boolean sticky = BlockStateValues.isStickyPiston(blockId);
+ BlockState state = session.getGeyser().getWorldManager().blockAt(session, position);
+ boolean sticky = state.is(Blocks.STICKY_PISTON);
boolean extended = action != PistonValueType.PUSHING;
return new PistonBlockEntity(session, pos, direction, sticky, extended);
});
@@ -109,11 +112,7 @@ public class JavaBlockEventTranslator extends PacketTranslator